【问题标题】:Java generics incompatible types compilation error for generic static method call in Oracle Java SE 8u20 JDKOracle Java SE 8u20 JDK 中泛型静态方法调用的 Java 泛型不兼容类型编译错误
【发布时间】:2014-09-28 19:29:30
【问题描述】:

使用 Oracle Java SE 8u20 JDK 编译以下代码时,前三个赋值编译正常(对于 works* 变量),但第四个赋值(对于 fails1 变量)生成以下编译错误:

错误:

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 错误报告的引用将不胜感激。

感谢您的帮助。

【问题讨论】:

  • 它也不能在 Java 7 上编译。
  • 请记住,类型擦除永远不是解决编译错误的方法,例如您当前的错误。在编译时没有擦除——所有类型信息都在那里。
  • 我推荐阅读这个问答:stackoverflow.com/questions/3652718/…
  • @MarkoTopolnik:您的链接中的答案给了我解决方案,我将在下面回答。谢谢。

标签: java generics compilation type-erasure incompatibletypeerror


【解决方案1】:

&lt;&gt; 之间的任何内容都是类型不变的,除非您使用 ? 通配符。

Set&lt;? extends Object&gt;Set&lt;Object&gt; 的类型不同,因此需要类型变化才能被认为是兼容的。

如果它们在顶层,对于works1,顶层Set&lt;&gt; 之外,因此正常的Java 类型差异有效,但对于fails1,它们在&lt;&gt; 内,所以类型是不变的。

可以在&lt;&gt; 中启用类型差异,方法是将类型声明的最外层部分从Set&lt;Set&lt;...&gt;&gt; Set&lt;? extends Set&lt;...&gt;&gt; 更改。

因此,以下代码编译正确:

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

【讨论】:

    【解决方案2】:

    您在fails1 上的输入过于严格,这与在声明时对其施加的相对宽松的通配符约束相矛盾。

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

    本质上,您正在尝试采取:

    Set<Set<? extends Object>>
    

    这是一组集合,其中包含 Object 或扩展 Object...

    ...把它变成这样:

    Set<Object>
    

    只是一组Object类型。

    works1 不会发生这种情况是有原因的:它定义了一个 Set,其中包含 ObjectObject 的后代的元素,并且由于 Object 满足至少其中一项要求,在后台执行的capture conversion 将满足此规则。

    再一次,这是您正在使用的 Java 8 - 除非 Java 的编译器无法在此处进行类型推断,否则您传递这些类型几乎没有什么收获。

    【讨论】:

    • 我认为最重要的信息应该是顶层的? 和嵌套位置的? 之间的区别。即,为什么您的解释不适用于works1。从表面上看,那里还有一个过于严格的右手边。不同之处在于顶级? 会被通配符捕获,而嵌套的则不会。
    • 这不是一个坏主意。我会在大约半小时内完成。将尝试以一种令人满意的方式来制定它。
    猜你喜欢
    • 2011-04-18
    • 2010-11-19
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-10
    相关资源
    最近更新 更多