为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

繁星淼淼 2021-04-29 14:35:09
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 {}输出为ir.openuniverse.C。为什么?我希望D!
查看完整描述

3 回答

?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

编译期间,Java的类型擦除更改


class B<T extends C> {

public T t;

}

至 :


class B<C> {

public C t;

}

由于getType()标识了字段的声明类型,因此输出为ir.openuniverse.C


查看完整回答
反对 回复 2021-05-19
?
弑天下

TA贡献1818条经验 获得超8个赞

谢谢大家的帮助。最后,我被迫将A的定义更改为:


class A extends B<D> {

    public D t;

}

就我的目的而言已经足够了(尽管我一点都不喜欢它!)。


编辑:


超越方式不是基本方式。请参阅下面的@DanielPryden的前两个注释。


替代解决方法:


class A extends B<D> {

    @Override public D getT() { return super.getT(); }

}


class B<T extends C> {

    private T t;

    public T getT() { return t; }

}

并在main():


System.out.println(A.class.getMethod("getT").getReturnType().getName());

输出: ir.openuniverse.D


另一种方式:


注意:这不是解决主要问题的方法(请参阅下面的@DanielPryden的第四条评论)。但是也许可以帮助您(像我一样)。


当您至少有以下一个实例时,可以使用此解决方法A:


public class Main {

    public static void main(String[] args) {

        A a = new A();

        System.out.println(a.t.getClass().getName());

        // Or via reflection:

        // System.out.println(a.getClass().getField("t").get(a).getClass().getName());

    }

}


class A extends B<D> {

    { t = new D(); }

}


class B<T extends C> {

    public T t;

}

输出: ir.openuniverse.D


查看完整回答
反对 回复 2021-05-19
  • 3 回答
  • 0 关注
  • 120 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信