Java 9中类型推断检查的变化

Moz*_*far 8 java generics type-inference java-9

代码(缩短实际代码来解释问题).

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

测试

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> 
Run Code Online (Sandbox Code Playgroud)

请注意在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 
Run Code Online (Sandbox Code Playgroud)

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 
Run Code Online (Sandbox Code Playgroud)

注意到Java 9编译的反汇编代码的不同之处,它明确地检查了相关指令中的类型.当然,应该很容易从代码中推断出返回类型应该是字符串,但之前没有明确的检查.

问题:Java 9中的类型推断是否有一些变化并添加显式检查?如果是,我在哪里可以找到详细信息(在更改日志中找不到)?是否在Java 9中更改了一些在java 9中添加此显式类型检查的编译默认选项?

谢谢,Mozaffar

Eug*_*ene 6

看起来这是java-8中的一个错误,很可能就是这个错误.它在java-9中得到修复.在checkcast必须用有,因为你只需要开始Abc<String>输入,在我看来.