代码(缩短了实际代码以解释问题)。
import java.util.Map;
import java.util.HashMap;
public class TypeReferenceTest {
public static class Model {
public void setAbc(Abc<String> abc) { }
}
public static class Abc<T> {
public Abc(T val) { }
}
public static void main(String[] args) {
Map<String, Object> attrMap = new HashMap<>();
attrMap.put("key", 0);
Model m = new Model ();
m.setAbc(new Abc<>(getAttrOrDefault(attrMap, "key", "Default")));
System.out.println("Test completed.....");
}
public static <T extends Object> T getAttrOrDefault(Map<String, Object> attrMap, String attrName, T defaultValue) {
@SuppressWarnings("unchecked")
T attrValue = (T)attrMap.get(attrName);
return (attrValue == null) ? defaultValue : attrValue;
}
}
测试
host:~/temp/test> /usr/local/java/jdk1.8/bin/javac TypeReferenceTest.java
host:~/temp/test> file TypeReferenceTest.class
TypeReferenceTest.class: compiled Java class data, version 52.0 (Java 1.8)
host:~/temp/test> /usr/local/java/jdk9/bin/java TypeReferenceTest
Test completed.....
host:~/temp/test> /usr/local/java/jdk9/bin/javac TypeReferenceTest.java
host:~/temp/test> file TypeReferenceTest.class
TypeReferenceTest.class: compiled Java class data, version 53.0
host:~/temp/test> /usr/local/java/jdk9/bin/java TypeReferenceTest
Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String
at TypeReferenceTest.main(TypeReferenceTest.java:18)
host:~/temp/test>
请注意在 Java 9 编译代码上运行相同代码时的异常。我理解代码导致 ClassCastException 的原因,但是如果代码是用 Java 8 编译的(两种情况下运行时都是 Java 9)就可以了。为了查看差异,我使用了 javap 并反汇编代码以查看差异。
Java 8 编译反汇编代码(这里只有感兴趣的部分)
39: invokestatic #11 // Method getAttrOrDefault:(Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
42: invokespecial
Java 9 编译反汇编代码(这里只是感兴趣的部分)
39: invokestatic #11 // Method getAttrOrDefault:(Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
42: checkcast #12 // class java/lang/String
45: invokespecial
注意到 Java 9 编译反汇编代码的差异,它在相关指令中明确检查类型。当然,从代码中应该很容易推断出返回类型应该是字符串,但之前没有明确检查。
问题:Java 9 中的类型推断和添加显式检查是否有一些变化?如果是,我在哪里可以找到详细信息(在变更日志中找不到)?是否在 Java 9 中更改了某些编译默认选项以在 Java 9 中添加此显式类型检查?
谢谢, 莫扎法尔
最佳答案
看起来这是 java-8 中的一个错误,很可能是 this one .它在 java-9 中得到修复。 checkcast
必须在那里开始,因为你只需要 Abc<String>
作为输入,在我看来。
关于java - Java 9 中类型推断检查的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54181882/