【问题标题】:Why does this code compile fine in java 11?为什么这段代码在 java 11 中编译得很好?
【发布时间】:2020-06-02 07:23:04
【问题描述】:

代码如下:

import java.util.*;

public class Main {
    public static <T> T defaultIfNull(T object, T defaultValue) {
        return object != null ? object : defaultValue;
    }

    public static void main(String[] args) {
        List<String> ls = Collections.emptyList();
        List<String> lo = defaultIfNull(ls, Collections.emptyList());
    }
}

使用openjdk 11,编译正常:

root@debian:~/tmp# java -version
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Debian-1deb10u1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Debian-1deb10u1, mixed mode, sharing)

root@debian:~/tmp# javac ./Main.java

但是,openjdk 1.8 的情况并非如此:

root@debian:~/tmp# /usr/local/java-se-8u41-ri/bin/java -version
openjdk version "1.8.0_41"
OpenJDK Runtime Environment (build 1.8.0_41-b04)
OpenJDK 64-Bit Server VM (build 25.40-b25, mixed mode)
root@debian:~/tmp# /usr/local/java-se-8u41-ri/bin/javac ./Main.java
./Main.java:12: error: incompatible types: inferred type does not conform to upper bound(s)
        List<String> lo = defaultIfNull(ls, Collections.emptyList());
                                       ^
    inferred: List<? extends Object>
    upper bound(s): List<String>,Object
1 error

这里的问题是,如果没有提供类型参数,Collections.emptyList 返回List&lt;Object&gt;。那么,是什么让openjdk 11 可以做同样的事情呢?

【问题讨论】:

  • 我尝试在一些在线编译器上运行代码,它在 11.0.4 和 1.8.0_66 版本上都编译得很好。
  • @Amongalen 事实上,IntelliJ 在启用1.8 的情况下也可以正常编译(在我的单独设备上)。我不确定是什么导致了这个问题。
  • 也许您应该尝试在具有完全相同版本的 openjdk 的单独设备上编译它。我只能猜测这是导致问题的一些错误。
  • @Amongalen 嗯,你能解释一下为什么它应该起作用吗?在这种情况下,我不确定emptyList 如何返回List&lt;String&gt;。这肯定会证明为什么后者是一个错误。
  • Java 8 Update 41 非常旧,最新的是 Java 8 Update 252。

标签: java generics type-inference


【解决方案1】:

这是一个bug in the javac tool(如here 所列),已在更高版本中修复。您应该将您的 jdk 更新到较新的版本以解决此问题(并同时应用安全补丁)。

此外,如果无法更新您的 jdk 版本,您可以通过指定类型来帮助编译器,如下所示:

List<String> lo = Main.<List<String>>defaultIfNull(ls, Collections.<String>emptyList());

虽然我没有对此进行测试,因为我不使用您的版本,但它可能适用于这种情况。

【讨论】:

  • 谢谢!你能详细说明为什么它应该起作用吗?我不确定,如果不指定 &lt;String&gt;emptyList 如何返回 List&lt;String&gt;
  • @b1sub 这就是type inference 的工作原理。您也可以指定类型,但通常没有必要。编译器能够自己找出类型。
  • 好的。我会进一步挖掘它。感谢您的回答。
猜你喜欢
  • 2015-08-21
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
  • 2017-11-09
  • 2012-07-06
相关资源
最近更新 更多