我们有以下代码:
class MyClass<T>{
public void method(){
List<T>= new ArrayList<T>();
}
}
以下原因是否正确?我们尝试从非静态方法实例化
ArrayList<T>
,其中T
是类型参数。 method
在MyClass<T>
的特定实例中需要。对于即时MyClass<T>
编译器必须明确知道类型T
。据我了解,在非静态上下文中,编译器标记类型参数T
众所周知,因此我们可以实例化ArrayList<T>
。但是,如果我们编写以下代码:
class MyClass<T>{
public void method(){
List<T>= new ArrayList<T>();
new T();// Compile Error
}
}
我们有一个编译错误。我知道我们可以应用抽象工厂模式或针对此需求使用反射。但是
new
运算符需要特定的类型。参数类型T
是特定于非静态上下文的。我在哪里推理错误? 最佳答案
据我了解,编译器在非静态上下文中的标记类型参数T是已知的,因此我们可以实例化ArrayList。
否。即使在非静态上下文中,编译器也不知道T
表示什么类型。 new ArrayList<T>();
起作用的原因是,编译器知道ArrayList<E>
具有0-arg构造函数。类型参数T
将仅由实际类型参数替换。它可以是任何类型。并且由于您可以创建任何类型的ArrayList
,所以很好。
但是新的运算符需要特定的类型。类型参数T是特定于非静态上下文的。我在哪里推理错误?
对于new T();
,由于编译器不知道T
是什么类型,因此也不知道是否存在T
的任何可访问0-arg构造函数。考虑如下类:
class Test {
private int value;
public Test(int value) { this.value = value; }
}
然后将实例化为:
MyClass<Test> obj = new MyClass<Test>();
现在,假设编译器允许
new T();
,那么对于此实例化,就像-new Test();
。但是Test
中没有0-arg构造函数。那么,您如何期望代码在运行时运行?它肯定会引发异常。编译器通过显示编译器错误来防止此情况。我们可以通过指定一个绑定-
T
向类型参数T extends Number
添加更多信息。但这只会允许我们访问类型参数的方法。构造函数仍然无法访问。