为什么这段代码在 java 11 中编译得很好?



这是代码:

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<Object>。那么,是什么让openjdk 11做同样的事情变得可以呢?

这是javac工具中的一个错误(如此处所列(,已在更高版本中修复。您应该将 jdk 更新到较新版本以解决此问题(并应用安全补丁(。

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

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

不过我还没有测试过这个,因为我不使用你的版本,但它在这种情况下可能有效。

最新更新