为什么无法创建类型形参的实例?

时间:2018-09-05 06:41:52

标签: java generics

在Java中,创建type参数的实例是非法的,因此以下代码将不起作用:

class Gen<T> {
    T ob;
    Gen() {
        ob = new T(); // Illegal!!!
    }
}

其背后的原因是:

  

T在运行时不存在,那么编译器将如何知道   要创建的对象的类型。

但是我无法理解的是,使用erasure,以下代码将转换为:

class Gen {
    Object ob;
    Gen() {
        ob = new Object(); // Perfectly Fine!!!
    }
}

因为:

  

编译Java代码时,所有通用类型信息为   删除(删除)。这意味着用其替换类型参数   绑定类型,如果未指定显式绑定,则为Object

那么为什么实例化type参数是非法的?

2 个答案:

答案 0 :(得分:11)

简单:因为T可以是任何东西。

假设您有一个Gen<Integer>。惊喜:整数没有默认的构造函数。那么您打算如何new Integer()呢?

编译器无法知道是否存在作为T传入的事物的默认构造函数。

java.lang.Object显然具有这样的构造函数。

答案 1 :(得分:0)

在运行时类型未知时是非法的。这是由于类型擦除。

但是,如果您通过传递类型的类来为方法或构造函数提供有关类型的信息,则只要有合适的构造函数,就可以使用反射实例化该类型的对象。

例如,这是可能的:

import javax.swing.*;

public class Gen<T> {

    T ob;
    Gen(Class<T> tClass) throws IllegalAccessException, InstantiationException {
        ob = tClass.newInstance(); // legal if class has default constructor!!!
    }

    public T getOb() {
        return ob;
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        Gen<JFrame> genFrame = new Gen<>(JFrame.class);
        if((genFrame.getOb() == null)) {
            throw new IllegalStateException();
        }
        Gen<JPanel> genPanel = new Gen<>(JPanel.class);
        if(genPanel.getOb() == null) {
            throw new IllegalStateException();
        }
    }
}