我们有以下代码:
class MyClass<T>{
public void method(){
List<T>= new ArrayList<T>();
}
}
以下原因是否正确?我们试图从非静态方法实现ArrayList<T>
T
,其中method
是类型参数。 MyClass<T>
的特定实例中需要MyClass<T>
。对于instanciate T
编译器必须明确知道类型T
。据我所知,编译器在非静态上下文中标记类型参数ArrayList<T>
已知,因此我们可以实现class MyClass<T>{
public void method(){
List<T>= new ArrayList<T>();
new T();// Compile Error
}
}
。
但是如果我们写下面的代码:
new
我们有编译错误。我知道我们可以应用抽象工厂模式或使用反射来满足这种需求。但T
运算符需要特定类型。类型参数{{1}}是特定的非静态上下文。我的错误推理在哪里?
答案 0 :(得分:3)
据我了解,编译器在非静态上下文中标记类型参数T已知,因此我们可以实现ArrayList。
没有。即使在非静态上下文中,编译器也不知道T
表示什么类型。 new ArrayList<T>();
工作的原因是,编译器知道ArrayList<E>
有一个0-arg构造函数。类型参数T
将被实际类型参数替换。它可以是任何类型。由于您可以创建任何类型的ArrayList
,这很好。
但新操作员需要特定类型。类型parametr T是特定的非静态上下文。我的错误推理在哪里?
对于new T();
,由于编译器不知道T
是什么类型,因此它不知道是否存在{{1}的任何可访问的0-arg构造函数} 或不。考虑如下课程:
T
然后将您的泛型类实例化为:
class Test {
private int value;
public Test(int value) { this.value = value; }
}
现在,假设编译器允许MyClass<Test> obj = new MyClass<Test>();
,那么对于此实例化,它就像在做 - new T();
。但new Test();
中没有0-arg构造函数。那么,您希望代码在运行时如何运行?它肯定会抛出异常。这是编译器通过显示编译器错误来阻止的。
我们可以通过指定绑定 - Test
向类型参数T
添加更多信息。但这只会让我们访问类型参数的方法。构造函数仍然无法访问。
答案 1 :(得分:2)
编译器如何知道类T(在运行时不存在)会有一个没有参数的构造函数?由于没有办法保证这一点,显然不应该允许!