不兼容的类型和新的类型变量

时间:2013-12-12 12:44:39

标签: java generics

我收到以下编译信息:

[javac]   ... error: incompatible types
[javac]         exceptionClassHolder = new Holder<>( (new Exception()).getClass() );
[javac]                                ^
[javac]   required: Holder<Class<? extends Exception>>
[javac]   found:    Holder<Class<CAP#1>>
[javac]   where CAP#1 is a fresh type-variable:
[javac]     CAP#1 extends Exception from capture of ? extends Exception
[javac] 1 error

在我看来,根据信息所有应该是正确的。 CAP#1确实扩展了Exception。那么如何理解上述信息呢?下面的SSCCE(最初没有发布,因为我希望在一般情况下理解错误消息本身):

class Holder<T> {
    public T t;
    public Holder(T t) {
       this.t = t;
    }
}

public class FooMain {
    public static void main(String args[]) throws Exception {
        Holder<Class<? extends Exception>> exceptionClassHolder;
        exceptionClassHolder = new Holder<>( (new Exception()).getClass() );
    }
}

2 个答案:

答案 0 :(得分:23)

不幸的是,现有的答案并没有解释这里发生了什么。首先,解决方案是简单地指定Holder的类型参数:

Holder<Class<? extends Exception>> exceptionClassHolder;
exceptionClassHolder =
        new Holder<Class<? extends Exception>>(new Exception().getClass());

您的版本无效的原因是new Exception().getClass()返回Class<? extends Exception>,其中?wildcard capture(在编译器错误消息中称为{{ 1}})。由于您将“菱形运算符”与CAP#1一起使用,编译器会为new Holder<>推断Class<CAP#1 extends Exception>,因此T是所创建对象的类型。

但是,这与您声明的Holder<Class<CAP#1 extends Exception>>类型不符。它使用nested wildcard,但不会捕获:Holder<Class<? extends Exception>> 某些特定类型延伸CAP#1 extends Exception,嵌套Exception代表字面任何类型扩展? extends Exception

虽然ExceptionClass<CAP#1 extends Exception>的子类型,但Class<? extends Exception>不是Holder<Class<CAP#1 extends Exception>>的子类型,因为generics aren't covariant,因此分配失败。

通过为Holder<Class<? extends Exception>>手动指定Class<? extends Exception>,可以帮助编译器避免使用此“陷阱”。

在这些帖子上查看我的类似答案:

答案 1 :(得分:2)

    Holder<? extends Class<? extends Exception>> exceptionClassHolder;
    exceptionClassHolder = new Holder<>( (new Exception()).getClass() );

原因是

  1. 因为您没有使用Exception.class而是使用Exception对象,所以java认为? extends Exception是必需的。
  2. 同样适用于getClass(),同样需要? extends Class,尽管Class是final。
  3. 当然有一天会简化。