为什么泛型类的实例类与泛型类不同?

时间:2016-12-17 00:21:10

标签: generics java-8 generic-type-argument

编辑:更简单的例子:

public <T> void shouldBeAbleToGetClassOfT(T t) {
    Class<T> tClass;

    // OK, but shows "unchecked cast" warrning.
    tClass = (Class<T>) t.getClass();

    // Compilation error!
    tClass = t.getClass();
}
  

不兼容的类型。

     

必需:类&lt; T&gt;

     

发现:类&lt; capture&lt;?扩展java.lang.Object&gt;&gt;

我对下面示例中的类型擦除感到有点困惑:

public static class Example<T> {
    private final T t;

    public Example(final T t) {
        this.t = t;
    }

    public <U extends T> void test(Consumer<T> consumer, U u) {
        // OK, but shows "unchecked cast" warrning.
        consumer.accept((T) t.getClass().cast(u));

        // OK, but shows "unchecked cast" warrning.
        consumer.accept(((Class<T>)t.getClass()).cast(u));

        // Compilation error!
        consumer.accept(t.getClass().cast(u));
    }
}

有问题的错误是:

  

错误:(21,46)java:不兼容的类型:java.lang.Object无法转换为T

这到底发生了什么?

.getClass()返回值是否已删除?为什么呢?

处理此错误的最佳方法是什么?

编辑:这是一个更复杂的用例,与我的问题更密切相关:

public class A<T> {
    private final T t;

    public A(final T t) {
        this.t = t;
    }

    public void printClass() {
        // OK, but shows "unchecked cast" warrning.
        B<T> b = new B<>((Class<T>) t.getClass());

        // Compilation error!
        B<T> b = new B<T>(t.getClass());

        b.printClass();
    }
}

public class B<T> {
    private final Class<T> t;

    public B(final Class<T> t) {
        this.t = t;
    }

    public void printClass() {
        System.out.println(t);
    }
}

1 个答案:

答案 0 :(得分:4)

来自getClass的文档:

  

实际结果类型为Class<? extends |X|>,其中| X |是擦除调用getClass的表达式的静态类型。

t的静态类型为T,其删除为Object。这意味着t.getClass()具有静态类型Class<? extends Object>,而不是您所期望的Class<? extends T>

由于t.getClass()具有静态类型Class<? extends Object>,编译器只知道t.getClass().cast(u)Object,而不是T。这意味着您无法将其传递给consumer.accept