分配给泛型类型的Java原始类型值运行时getClss()方法错误

woo*_*ird 5 java generics casting runtime

public class Box<T> {
    private T t;
    public Box(T t){
        this.t = t;
    }
    public void add(T t) {
      this.t = t;
    }
    public T get() {
      return t;
    }
    public static void main(String[] args) {
      Box<Integer> b = new Box(new String("may be"));
      System.out.println(b.get()); // successfully print out "may be"
      System.out.println(b.get().getClass()); // error
   }
}
Run Code Online (Sandbox Code Playgroud)

此代码给出了运行时错误:

exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
Run Code Online (Sandbox Code Playgroud)
  1. 为什么b.get()不触发运行时错误?
  2. 为什么只有在我尝试获取类变量的类时才会发生运行时错误?

更确切地说:为什么编译器第二个checkcast字节码中插入指令(导致异常)? get()

Gho*_*ica 2

请注意:

\n
    \n
  • 在第一种情况下, 的结果get()用于println(Object): 换句话说:接收方期望一个对象,并且该“条件”将始终为真。
  • \n
  • 在第二种情况下,将随后对返回的对象进行方法调用。现在,如果返回的类型是预期的类型,则可以产生巨大的差异。因此编译器添加此检查以保证以下方法调用是正确的
  • \n
\n

作为背景知识,可以查看 Java 语言规范,第 5.52 章:

\n
\n

演员阵容是经过检查的演员阵容。

\n

这样的强制转换需要运行时有效性检查。如果运行时的值为 null,则允许强制转换。否则,令 R 为运行时引用值所引用的对象的类,并令 T 为强制转换运算符中命名的类型的擦除 (\xc2\xa74.6)。强制转换必须在运行时通过 \xc2\xa75.5.3 中的算法检查类 R 是否与类型 T 的赋值兼容。

\n
\n

分别第 5.53 章运行时检查的转换

\n