Java 为什么工厂模式中的包装类型参数会围绕类型擦除工作?

Java 为什么工厂模式中的包装类型参数会围绕类型擦除工作?,java,generics,Java,Generics,从 你不能做“新E”。但是你可以把它改成 private static class SomeContainer<E> { E createContents(Class<E> clazz) { return clazz.newInstance(); } } 私有静态类SomeContainer { E createContents(类clazz) { 返回clazz.newInstance(); } } 这是一种痛苦

你不能做“新E”。但是你可以把它改成

 private static class SomeContainer<E>
 {
     E createContents(Class<E> clazz)
     {
         return clazz.newInstance();
     }
 }
私有静态类SomeContainer
{
E createContents(类clazz)
{
返回clazz.newInstance();
}
}
这是一种痛苦。但它是有效的。将其包装在工厂模式中会使 这更容易忍受一点

我想知道为什么这个方法有效

为什么类型擦除不应用于
类clazz
,因此它变成
类clazz
,然后
clazz.newInstance()
返回
对象的实例


谢谢。

类型擦除确实适用于
,但在运行时它只会变成
。但它仍然是在运行时传递到方法中的特定类的
对象

返回其类型参数,这里是
E
,因此编译器知道它将返回正确的类型。但是
newInstance
方法在运行时返回JVM中的
对象

在调用代码中,编译器根据调用代码中的
E
插入正确类型的强制转换。例如,代码:

Foo f = new EnclosingClass.SomeContainer<Foo>().createContents(Foo.class);

这里的工厂模式只是使用
Class
对象为运行时提供类型。

类型擦除并不意味着
clazz
变成
Class
。这意味着它将成为一个简单、朴素的
实例。
newInstance
方法将始终调用类对象表示的类型的构造函数,因为这是它的全部用途。在功能上,
对象表示的类型根本不在泛型中编码。您可以通过记住
Class
对象和
newInstance
在Java 1.5引入泛型之前工作得很好来直观地理解这一点。

它确实以同样的方式应用于它,区别在于运行时实际的
clazz
对象仍然知道它是什么类型,因此,它可以创建一个实例。你有一个实际的某物实例,而不仅仅是一个类型
E
。因为类型擦除并不意味着
clazz
变成
Class
。这意味着它将变成
Class
,而
newInstance
方法将返回一个适当的实例,因为多态性首先是如何工作的。这就是将
引用放在首位的全部意义。不确定是什么让你在这里绊倒了。通读源代码意味着:“深度魔法”。这并不是在试图咆哮。代码实际上调用了一个能够委托给本机实例化器的类。它还可以在一个分支中调用
Unsafe
。此外,此方法(最终)执行对
E
的转换,这使它能够正常工作,但仅从阅读代码就很难推断。请注意,
供应商
是传递某些内容以生成实例的更好方法,因为它正确处理泛型类型。
Foo f = (Foo) new EnclosingClass.SomeContainer().createContents(Foo.class);