2016-12-17 166 views
3

编辑:更简单的例子:为什么泛型类型的实例类与泛型类不一样?

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(); 
} 

Incompatible types.

Required: Class<T>

Found: Class<capture<? extends java.lang.Object>>

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

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)); 
    } 
} 

有问题的错误是:

Error:(21, 46) java: incompatible types: java.lang.Object cannot be converted to 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); 
    } 
} 
+4

你为什么需要显式演员?从编译器的角度来看,'U u'已经是'T'了,因为'U扩展T',所以'Consumer '应该随时接受'U'!只要删除演员阵容,并开心,或者如果这是你正在努力的其他事情,反而描述你原来的问题。 –

+0

@NándorElődFekete澄清,我添加了一个更复杂的例子,与我的问题更密切相关。 – Jezor

回答

4

从文档的getClass

The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called.

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

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

+0

我明白了。你将如何处理这个问题呢? '@ SuppressWarnings'? – Jezor

+3

@Jezor:这将取决于你的实际使用情况。通常情况下,你甚至不应该处于这种情况。 'Class.cast'很奇怪,很少需要。在你的例子中'Class.cast'和'U'都是多余的。 – user2357112

+0

事情是,实际使用情况要复杂得多,所以我想尽可能以最少的示例发布。 – Jezor