当前位置: 首页 > 知识库问答 >
问题:

JDK 11.0.2 编译在匿名参数化类类型推理上使用 javac NPE 失败

艾泉
2023-03-14

代码(sping-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.nullPointerexceptscapely@11.com.com.flowanaly.visitApply(Flow.java:1235) 在 jdk.compiler/com.com.com.tools.javac.tree.JCTree$JC 方法调用.accept(JCTree.java:1634) 在 jdk.compiler/com.com.com.tools.javac.tree.scan(TreeScanner.java:49) 在 jdk.compiler/com.com..java com.{5}.gac.trunk.dple.comlyly.1235:398) 在 jdk.编译器/com.sun.tools.comp.flow$FlowAnalyzer.visitVarDef(Flow.java:989)
...

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

新参数化类型参考

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

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


共有3个答案

钱修雅
2023-03-14

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

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

并称之为:

ResponseEntity<Object> test = restTemplate.exchange(
"https://example.com",
HttpMethod.GET,
new HttpEntity<>(headers),
createParameterizedTypeReference() { 
});
辛意智
2023-03-14

如前所述,问题在于参数化匿名类,例如,当使用来自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版本中尝试过,所有版本都包含该错误。

西门淮晨
2023-03-14

Bug(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开始提供。

 类似资料:
  • 我创建了一个模板类,其中构造函数采用std::function对象。第一个模板参数指示该函数的返回值。第二个参数定义该函数的参数类型。 关于使用函数std::function 它尝试使用基本版本。但第二个参数当然丢失了。如果我指定它编译的模板参数。 那么,为什么选择基本模板作为executorSpecialization2呢?甚至可以在这里对void使用类型推断,而不需要传递模板参数吗? 谢啦

  • 我正在创建一个接口和链表的实现,如Java1.8: 接口没有编译器问题,但给出了错误其中我有

  • 考虑以下示例: 而且,如果我们将非类型模板参数的类型改为占位符类型,如下所示: 然后,GCC接受,而Clang拒绝它(两者都拒绝,如上)。 海合会演示,铿锵演示。 (1)GCC HEAD 11.0.0 202 10117和Clang HEAD 12.0.0(20210118),。

  • 问题内容: 我试图动态加载文本文件并进行编译。 然后,我稍后将加载已编译的.class文件: 我目前遇到两个问题:首先是我加载的.java文件是否包含匿名类。看来JavaCompiler类不会编译它们。线程“主”中的异常java.lang.IllegalAccessException:类Loader.ClassLoader无法使用修饰符“”访问类Files.myname.myclass $ 1的成

  • 匿名参数的一个缺陷是你不能轻易让一个方法使用其作为参数或返回值。因为编译器产生的匿名类型,你不能用来作为方法的参数或返回值。这个问题的任何解决方案都是与局限的。你可以使用匿名类型作为泛型类型参数,或者传给参数为 System.Object 的方法。这些都不会觉得特别满意。泛型方法只能假设类型定义在 System.Object 的功能。 System.Object 同样也有局限。当然,有些时候,你会

  • 我遇到了一个奇怪的行为,在类型为“具体化”的函数中使用Gson进行反序列化。仅当类型参数中涉及接口时才会发生这种情况。 采用以下代码: 第4行使用自定义扩展函数Gson。fromJson(json:String):T。 如果定义为具体化,则失败: 如果它被定义为普通类型参数,它就可以工作: (注意,使具体化在这里没有意义,只是想了解它在特殊用例中的影响) 使用具体化时的异常如下所示: