Mir*_*ili 0 java generics reflection type-erasure
package ir.openuniverse;
public class Main {
public static void main(String[] args) throws NoSuchFieldException {
System.out.println(A.class.getField("t").getType().getName());
}
}
class A extends B<D> {}
class B<T extends C> {
public T t;
}
class C {}
class D extends C {}
Run Code Online (Sandbox Code Playgroud)
输出是ir.openuniverse.C.为什么?我期待D!
编辑:
这个问题不是关于变通方法或替代方法.所以答案不是解决方法.对于其他方式,请参阅下面的回答.
这是因为类型擦除.
Java将您的泛型类编译B<T>为适合与可能引用它的所有类一起使用的字节代码,包括可能正在扩展的任何类B<T>.
由于T仅限于扩展类C,因此Java知道您可以分配的任何值都B.t将扩展C,因此它将您的类编译为等效类
class B {
C t;
}
Run Code Online (Sandbox Code Playgroud)
在这一点上,任何任务都t可以工作; 但是读取t会产生C,所以编译器必须做一些"魔术"来解决这个问题.具体来说,编译器在已知子类型的位置插入类型转换.如有必要,它还可以生成桥接方法.有关详细信息,请参阅答案顶部的链接.