需要不兼容的类型:Class <T> found:Class <CAP#1>其中T是一个类型变量

Mar*_*tus 6 java generics

以下代码:

public class A<T> {

    Class<T> klass;
    T instance;

    public A(T instance) {
        this.klass = instance.getClass(); // this requires an explicit cast to Class<T> to satisfy the compiler
        this.instance = instance;
    }
}
Run Code Online (Sandbox Code Playgroud)

汇编:

A.java:7: error: incompatible types
             this.klass = instance.getClass();
                                           ^
required: Class<T>
found:    Class<CAP#1>
where T is a type-variable:
  T extends Object declared in class A
where CAP#1 is a fresh type-variable:
  CAP#1 extends Object from capture of ? extends Object
1 error
Run Code Online (Sandbox Code Playgroud)

为什么编译器不满足instance.getClass()将始终生成Class<T>(因为instance是类型T)并且需要显式转换?我安全只是添加显式转换:

this.klass = (Class<T>) instance.getClass();
Run Code Online (Sandbox Code Playgroud)

...从而使编译器静音或者是否存在运行时意外的空间?如果没有,为什么编译器不能解决这个问题呢?

Jon*_*eet 11

为什么编译器不满足instance.getClass()将始终生成Class(因为实例是T类型)并且需要显式转换?

考虑一下:

A<Object> a = new A<Object>("Foo");
Run Code Online (Sandbox Code Playgroud)

呼叫instance.getClass()不会返回Class<Object>- 它将返回一个Class<String>.它们不是一回事,即使每一个String都是一个Object.

您可以将代码更改为:

Class<? extends T> klass;
Run Code Online (Sandbox Code Playgroud)

此时它在逻辑上是安全的,但它仍然需要强制转换,因为Object.getClass()它只是声明返回Class<? extends |T|>(根据JLS第4.3.2节):

该类型的方法调用表达式的getClassClass<? extends |T|>其中T是的类或接口搜寻(§15.12.1) getClass.

|T|部分是指类型擦除T,在这种情况下,只是将是Object.

当然,演员实际上并没有在执行时检查任何东西,你需要@SuppressWarnings("unchecked")完全静音编译器,但至少代码在这一点上具有逻辑意义.