"设置<?extends Class <?扩展Throwable >>"真的吗?

And*_*tin 18 java generics collections

我一直在使用一个小的泛型方法来创建来自vararg元素的集合,例如

public <T> Set<T> createSet( T... elements ) { ...
Run Code Online (Sandbox Code Playgroud)

然而,最近我遇到了编译器没有按照我的预期行事的情况.以下createSet()仅使用s3作品.

Set<Class<? extends Throwable>> s1 = createSet( Exception.class, RuntimeException.class );

Set<? extends Class<Throwable>> s2 = createSet( Exception.class, RuntimeException.class );

Set<? extends Class<? extends Throwable>> s3 = createSet( Exception.class, RuntimeException.class );
Run Code Online (Sandbox Code Playgroud)

任何人都可以清楚地解释为什么s3可以工作以及我的思考可能出错的问题是s1 - 这是我的初始编码?谢谢.

Mar*_*ers 10

问题只在于推理逻辑. s1如果您显式键入方法调用,则工作得很好(除了vararg警告)

Set<Class<? extends Throwable>> s1 = 
    this.<Class<? extends Throwable>>createSet( Exception.class, RuntimeException.class );
Run Code Online (Sandbox Code Playgroud)

但默认情况下,给定参数的返回类型是Set<Class<? extends Exception>>(我想因为它是最具体的可能性).你只需要给编译器一个提示,因为没有它,它本质上是试图这样做:

Set<Class<? extends Exception>> temp = createSet(Exception.class, RuntimeException.class);
Set<Class<? extends Throwable>> s1 = temp;
Run Code Online (Sandbox Code Playgroud)

这是不允许的,因为从视编译器的点,然后你可以把OutOfMemoryError.classtemp这将违反其类型.

编辑

s3对你Class<? extends Exception>有用的原因是因为a 可赋值给Class<? extends Throwable>:

//this works
Class<? extends Exception> exceptionRef = Exception.class;
Class<? extends Throwable> throwableRef = exceptionRef;
Run Code Online (Sandbox Code Playgroud)

等等extends关键字,给您从转换的能力Set<Class<? extends Exception>>Set<? extends Class<? extends Throwable>>:

//this works too
Set<Class<? extends Exception>> exceptionSetRef = ...;
Set<? extends Class<? extends Throwable>> throwableSetRef = exceptionSetRef;
Run Code Online (Sandbox Code Playgroud)

不幸的是,这可能不是你想要的,因为现在你不能放任何东西throwableSetRef.


soc*_*a23 4

我认为这是因为 Exception 和 RuntimeException 最接近的常见类型是 Exception,而不是 Throwable。调用 createSet() 时 T 被推断为,并且分配给类型的变量Class<? extends Exception>是非法的Set<Class<? extends Exception>>Set<Class<? extends Throwable>

这有效:

Set<Class<? extends Exception>> s1 = createSet( Exception.class, RuntimeException.class );
Run Code Online (Sandbox Code Playgroud)