Java 为什么工厂模式中的包装类型参数会围绕类型擦除工作?
从 你不能做“新E”。但是你可以把它改成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(); } } 这是一种痛苦
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);