为什么超类字段的泛型类型不会被删除到子类型中的具体绑定?

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!


编辑:

这个问题不是关于变通方法或替代方法.所以答案不是解决方法.对于其他方式,请参阅下面的回答.

das*_*ght 5

这是因为类型擦除.

Java将您的泛型类编译B<T>为适合与可能引用它的所有类一起使用的字节代码,包括可能正在扩展的任何类B<T>.

由于T仅限于扩展类C,因此Java知道您可以分配的任何值都B.t将扩展C,因此它将您的类编译为等效类

class B {
    C t;
}
Run Code Online (Sandbox Code Playgroud)

在这一点上,任何任务都t可以工作; 但是读取t会产生C,所以编译器必须做一些"魔术"来解决这个问题.具体来说,编译器在已知子类型的位置插入类型转换.如有必要,它还可以生成桥接方法.有关详细信息,请参阅答案顶部的链接.