java – 不兼容的类型和新鲜的类型变量

我得到以下编译消息:
[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确实扩展了异常.那么上述消息应该如何理解呢? 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() );
    }
}

解决方法

不幸的是,现有的答案并不能解释这里发生了什么.首先,解决方案是简单地指定Holder的类型参数:
Holder<Class<? extends Exception>> exceptionClassHolder;
exceptionClassHolder =
        new Holder<Class<? extends Exception>>(new Exception().getClass());

你的版本不起作用的原因是因为新的Exception().getClass()返回一个Class<?扩展异常>,哪里?是一个wildcard capture(在编译器错误消息中称为CAP#1).由于您使用新的“持有者”的“钻石经营者”,所以编译器推断出类别< CAP#1扩展了Exception>对于T等等,持有者< Class< CAP#1扩展例外>>是创建对象的类型.

但是,这与您所声明的持有者类型 >.它使用一个 nested wildcard,它不捕获:而CAP#1扩展的异常是一些特定类型扩展异常,嵌套?扩展异常表示任何扩展异常的类型.

而< CAP#1扩展例外>是Class的子类型扩展异常>,持有者<类< CAP#1扩展异常>>不是Holder< Class<?扩展异常>>因为generics aren’t covariant,所以分配失败.

通过手动指定Class<?扩展异常>对于T,你可以帮助编译器避免这个“陷阱”.

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

> Java: Wildcard Types Mismatch Results in Compilation Error
> Bounded-wildcard related compiler error

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...