Oracle Java SE 8u20中的泛型静态方法调用的Java泛型不兼容类型编译错误Java SE 8u20 JDK

问题描述:

使用Oracle Java SE 8u20 JDK编译以下代码时,前三个赋值可以正常编译(对于works*变量),但第四个赋值(用于fails1变量)生成以下编译错误:Oracle Java SE 8u20中的泛型静态方法调用的Java泛型不兼容类型编译错误Java SE 8u20 JDK

错误:

incompatible types: Set<Set<Object>> cannot be converted to Set<Set<? extends Object>> 

代码:

import java.util.Set; 
import java.util.Collections; 

... 

Set<? extends Object>  works1 = Collections.<Object>emptySet(); 
Set<Set<Object>>   works2 = Collections.<Set<Object>>emptySet(); 
Set<Set<? extends Object>> works3 = Collections.<Set<? extends Object>>emptySet(); 
Set<Set<? extends Object>> fails1 = Collections.<Set<Object>>emptySet(); 

我认为这是正确的(可能是由于Java语言规范中定义的某种类型的擦除),而不是一个错误,但我不确定。

有谁知道为什么fails1无法编译?对Java规范的适用部分或JDK错误报告的引用将不胜感激。

感谢您的任何帮助。

+0

它也不能在Java 7上编译。 – Makoto 2014-09-28 19:33:56

+0

请记住,类型擦除不会是编译错误(如当前错误)的答案。在编译时没有擦除---所有类型的信息都在那里。 – 2014-09-28 19:46:53

+0

我推荐阅读这个问答:http://*.com/questions/3652718/multiple-nested-wildcard-arguments-not-applicable – 2014-09-28 19:59:49

任何除非你使用?通配符类型不变。

Set<? extends Object> & 的类型不同,因此需要将类型差异视为兼容。

如果他们是在顶层,作为works1,*Set< & >外面,所以普通的Java类型变化的工作,但对于fails1,他们是< & >内,所以类型是不变的。

类型方差内< & >通过从Set<Set<...>>Set<? extends Set<...>>改变类型声明的最外部分被启用。

因此,下面的代码编译正确:

Set<? extends Set<? extends Object>> works4 = Collections.<Set<Object>>emptySet(); 

我衍生我的答案从回答以下问题(这是由@MarkoTopolnik如上所述):

multiple nested wildcard - arguments not applicable

的回答以下问题提供了更详细的解释:

Can't cast to to unspecific nested type with generics

您在fails1上输入的内容过于狭窄,这与在声明时强加给它的相对较松散的通配符限制相矛盾。

形式为? extends Tupper-bounded wildcard意味着您愿意接受T及其所有子类型。但是,您明确限制右侧为Object

从本质上说,你要采取:

Set<Set<? extends Object>> 

这是一组包含的东西是一个Object或扩展Object套...

......并把它成这样:

Set<Object> 

其是仅一套Object类型。

还有一个原因,这种情况不符合works1发生:它定义了一个Set其中包含的一些元素是ObjectObject后裔,自Object满足这些要求的至少一个,该capture conversion之中在后台完成将履行这一规则。

然后,这就是您正在使用的Java 8 - 除非Java的编译器无法在此处进行类型推断,否则在您传递这些类型时根本没有什么收获。 < & >之间

+0

我认为最重要的信息应该是顶层'?'和嵌套位置'''之间的区别。也就是说,为什么你的解释不适用于'works1'。在表面上看,这里的限制性右边也是如此。不同之处在于*'?'受到通配符捕获,而嵌套的不是。 – 2014-09-28 19:51:18

+0

这不是一个坏主意。我将在大约半小时内完成这项工作。试图用一种令人满意的方式来理解它。 – Makoto 2014-09-28 19:54:50