我得到以下编译消息:
[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扩展例外>>是创建对象的类型.
但是,这与您所声明的持有者类型
而< 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