我们有以下代码:

class MyClass<T>{
    public void method(){
        List<T>= new ArrayList<T>();
    }
}


以下原因是否正确?我们尝试从非静态方法实例化ArrayList<T>,其中T是类型参数。 methodMyClass<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添加更多信息。但这只会允许我们访问类型参数的方法。构造函数仍然无法访问。

08-05 06:24