JDK 11.0.2 编译失败,匿名参数化类类型推断上出现 javac NPE

问题描述 投票:0回答:8

代码(spring-web 5.1.2)

public static void main(String[] args) {
    RestTemplate restTemplate = new RestTemplate();

    HttpHeaders headers = new HttpHeaders();
    headers.set(HttpHeaders.AUTHORIZATION, "token");
    HttpEntity<Object> requestEntity = new HttpEntity<>(headers);

    ResponseEntity<Object> test = restTemplate.exchange(
            "https://example.com",
            HttpMethod.GET,
            new HttpEntity<>(headers),
            new ParameterizedTypeReference<>() { // fails here
            });
}

OracleJDK 1.8(预期输出)

无法推断类型参数 org.springframework.core.ParameterizedTypeReference

原因:不能将 '<>' 与匿名内部类一起使用

OracleJDK 11.0.2(非预期输出)

编译器消息文件损坏:key=compiler.misc.msg.bug 参数=11.0.2、{1}、{2}、{3}、{4}、{5}、{6}、{7} java.lang.NullPointerException 位于 jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitApply(Flow.java:1235) 在 jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInspiration.accept(JCTree.java:1634) 在 jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) 在 jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:398) 在 jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitVarDef(Flow.java:989)
...

如果我将菱形运算符更改为显式类型

new ParameterizedTypeReference<>(){}
new ParameterizedTypeReference<Object>(){}

然后代码在两个 JDK 上都能成功编译。

这是一个已知的编译器错误吗?

java javac type-inference java-11 compiler-bug
8个回答
65
投票

错误 (JDK-8212586) 已在版本 12 中提交并修复

最小的、可验证的示例:

public static void main(String[] args) {
    new Bug<>(){};
}

static class Bug<T> {

    Bug() {
        test(new ParameterizedTypeReference<>(){});
    }

    void test(ParameterizedTypeReference<T> typeReference) {
    }
}

一些细节。


修复也已向后移植到 JDK 11 - https://bugs.openjdk.java.net/browse/JDK-8220578

可从 JDK 11.0.4开始使用。


10
投票

正如之前的评论所指出的,问题出在参数化匿名类上,例如当使用 Guava 的 TypeToken 时,这工作:

public List<SomeClass> list() {
    return getData(new TypeToken<>() { });
}

但这确实有效:

public List<SomeClass> list() {
    return getData(new TypeToken<List<SomeClass>>() { });
}

我在11.0.3 - 11.0.7版本中尝试过,所有版本都包含该错误。


9
投票

我有同样的错误,你需要创建一个函数:

ParameterizedTypeReference<Object> createParameterizedTypeReference(){ return new ParameterizedTypeReference<>(){}; }

并称之为:

ResponseEntity<Object> test = restTemplate.exchange(
"https://example.com",
HttpMethod.GET,
new HttpEntity<>(headers),
createParameterizedTypeReference() { 
});

4
投票

Java 11.0.7也有同样的问题。

这更改自:

new ParameterizedTypeReference<>() {
})

对此:

new ParameterizedTypeReference<HashMap<String, MyClass>>() {
})

2
投票

我已经通过升级到 AdoptOpenJDK 11.0.8 在我的机器上解决了这个问题。

https://adoptopenjdk.net/installation.html#x64_mac-jdk


0
投票

大多数时候,此错误不会告诉您原始类,因此很难故意重现该问题。经过多次尝试,我终于将项目 JDK 更新到 11.0.16(从 11.0.7)并且成功了!


0
投票

万一其他人遇到这个问题:我们必须将 java 编译器从 javac 更改为 eclipse(任何其他不是 javac 的东西)才能编译我们的代码。升级/降级jdk并没有解决我们的问题。


0
投票

就我而言,我安装了 Oracle 的最新 java 11 (Java SE 开发工具包 11.0.19),它解决了问题。您可以在这里下载最新版本:https://www.oracle.com/pl/java/technologies/javase/jdk11-archive-downloads.html

© www.soinside.com 2019 - 2024. All rights reserved.