为什么我们可以在Java中创建泛型模板而不是泛型类型的新实例?

为什么我们可以在Java中创建泛型模板而不是泛型类型的新实例?,java,generics,Java,Generics,我知道不可能做到: new T其中T由于类型擦除而为泛型类型 那么,为什么可以做一些类似于newa的事情,其中T是泛型的?例如,为什么要编译下面的代码 static class A<T>{ T t; A(T t){ this.t=t; } } static class B<T>{ A<T> create(T t){ return new A<T>(t); } } publ

我知道不可能做到:
new T
其中
T
由于类型擦除而为泛型类型

那么,为什么可以做一些类似于
newa
的事情,其中T是泛型的?例如,为什么要编译下面的代码

static class A<T>{
    T t;
    A(T t){
        this.t=t;
    }
}

static class B<T>{

    A<T> create(T t){
        return new A<T>(t);
    }
}

public static void main (String[] args) throws java.lang.Exception
{
    A<Integer> a = new B<Integer>().create(3);
}
静态A类{
T;
A(T){
t=t;
}
}
静态B类{
A创建(T){
返回新的A(t);
}
}
公共静态void main(字符串[]args)引发java.lang.Exception
{
A=新的B()。创建(3);
}
因为
A
在编译和运行时都是定义良好的类型

在概念上的中间步骤,在:

new B<Integer>()
擦除后,
A
变为
A
,这是一种有效类型

您不能执行
newt
,因为
t
不是一个定义良好的类型,它只是一个标记。如果您确实需要,您可以获得相应的类并使用以下方法实例化
T
类型的对象:

public class GenericFactory {
    <T> T create(Class<T> c) throws Exception {
        return c.newInstance();
    }
}

是的,这很难看。

由于类型擦除,您可以实例化
新的A()
。如果Java将泛型实现为可修改的,那么如果没有用于查找
T
的运行时绑定的反射,这将不起作用


通过扩展,这是由于对象类型的非泛型方面是具体化的(可通过
getClass()
访问),编译器不可能发出这样的字节码,根据调用站点,它将能够实例化任何类型T。

您没有创建泛型模板的新实例。您正在使用常规模板创建对象的实例

new A<T>(t);
新的A(t);
创建一个新的
a
,它不是通用的。您不一定知道编译时
T
将是什么,但您知道对象将是
A
。事实上,它的美妙之处在于,您不必预测
T
将是什么,这允许您创建这样强大的代码,并且可以重用。想象一下,如果您实现了一个
堆栈
,那么您对实际的内容类型不感兴趣。您有兴趣很好地处理
top
pop
push
操作。如果不必预测元素是
整数
字符串
还是其他类型,则可以优雅地编写适用于许多不同类的通用代码

如果我必须预测什么是
T
,那么我宁愿说它是一个
对象
,并且能够处理任何对象。我相信事实上,类似的事情会在后台发生。另外,另一种选择是使用
反射
,但这一点也不干净

new GenericFactory().create(Integer.class);
new A<T>(t);