Sma*_*ker 13 java type-erasure type-parameter
当我在使用泛型时,我发现了一些东西.在下面的示例中,doStuff1
编译但doStuff2
不:
public <T extends Foo> void doStuff1(T value) {
Class<? extends Foo> theClass = value.getClass();
}
public <T extends Foo> void doStuff2(T value) {
Class<? extends T> theClass = value.getClass();
}
Run Code Online (Sandbox Code Playgroud)
所以,我查阅了文档Object.getClass()
,发现了这个:
实际的结果类型是Class <?extends | X |> where | X | 是调用getClass的表达式的静态类型的擦除.
这让我有点好奇.为什么getClass()
这样设计?如果适用的话,我可以理解将类型转换为它们的原始类,但我认为没有明显的理由为什么它们必须使它也被杀掉T
.有没有一个特定的原因,它也可以摆脱它,或者它只是一个普遍的"让我们摆脱一切因为它更容易;谁会永远需要它"的方法?
如果getClass()
回来Class<? extends X>
,没有什么不好的事情会发生; 实际上它会帮助很多用例.
唯一的问题是,它在理论上是不正确的.如果一个对象是一个ArrayList<String>
,它class
不可能Class<ArrayList<String>>
- 没有这样的类,只有一个Class<ArrayList>
.
这实际上与擦除无关.如果有一天Java获得完整的reified类型,getClass()
仍然应该返回Class<? extends |X|>
; 但是应该有一个新方法,比如getType()
可以返回更详细的方法Type<? extends X>
.(但是,getType
可能会与许多现有的类使用自己的getType
方法冲突)
对于时间安排,因为Class<? extends X>
在很多情况下可能有用,我们可以设计我们自己的方法来做到这一点
static <X> Class<? extends X> myGetClass(X x){ ... }
Run Code Online (Sandbox Code Playgroud)
但是可以理解他们不会把这种黑客放在标准的lib中.