分配给泛型类型运行时getClss()方法的Java原始类型值错误 为什么b.get()没有触发运行时错误 为什么只有在尝试获取类变量的类时才会发生运行时错误

分配给泛型类型运行时getClss()方法的Java原始类型值错误 为什么b.get()没有触发运行时错误 为什么只有在尝试获取类变量的类时才会发生运行时错误,java,generics,casting,runtime,Java,Generics,Casting,Runtime,更准确地说:为什么编译器只在第二个get()(导致异常)的字节码中插入checkcast指令 在代码行中框b=新框(新字符串(“可能”) 创建新的框时对象缺少类型信息,并假定为默认的对象类 Box b=newbox(newstring())这是正确的方法 --------增加-------- 在Objectclass的方法getClass()中,返回运行时class对象。当返回时,代码框生成getClass()方法以返回Class而不是Class 您使用new B(new String())创建

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

在代码行中
框b=新框(新字符串(“可能”)
创建新的
框时
对象缺少类型信息,并假定为默认的
对象

Box b=newbox(newstring())这是正确的方法

--------增加--------

Object
class的方法
getClass()
中,返回运行时
class
对象。当返回时,代码
生成
getClass()
方法以返回
Class
而不是
Class

您使用
new B(new String())创建了原始类型因此编译器传递了语法,但在调用
getClass()
时,它将内部对象
String
转换为
Integer
,并抛出RuntimeException

,请注意:

  • 在第一种情况下,
    get()
    的结果用于
    println(Object)
    :换句话说,接收方需要一个Object,并且“condition”总是true
  • 在第二种情况下,随后将对返回的对象调用方法。现在,如果返回的类型是预期的类型,那么它可以产生巨大的差异。因此,编译器正在添加此检查,以确保以下方法调用是可靠的
作为背景,我们可以了解Java语言规范,第5.52章:

该演员阵容为选中演员阵容

这样的强制转换需要运行时有效性检查。如果运行时的值为null,则允许强制转换。否则,设R为运行时引用值引用的对象类,T为强制转换运算符中指定类型的擦除(§4.6)。强制转换必须在运行时通过§5.5.3中的算法检查类别R的赋值是否与类型T兼容


分别在第5.53章。

此变量声明不一致

exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
它可以很好地编译,但在运行时会得到与 JVM将尝试将值强制转换为
Integer

Integer value = b.get();

当您调用:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
一切都很接近。

为什么这里需要
整数类?

在编译时,
b
被声明为
框b

因此编译器知道
b
是用
Integer
类型参数化的。
因此,编译后是的,泛型将被删除,但编译器会根据声明的代码添加一些强制转换。

这里就是这样。
对使用
Integer
参数化的变量调用
getClass()

但是
Class
是一个泛型类:
Class

因此编译器添加了对
Integer
的强制转换,以符合
Class

当然,通过对变量声明和实例化使用泛型:

System.out.println(b.get().getClass()); // error
Box b=新框(新字符串(“可能”);

这种不一致性是不可能的,因为编译器现在阻止您。

除了这里的答案之外,字节指令
checkcast
在类型检查时被调用,而类型检查不是
对象的具体类型。比如说

  Box<Integer> b = new Box<>(new String("may be"));
publicstaticvoidmain(字符串[]args){
框b=新框(新字符串(“可能”));
doStuff(b.get());//不需要检查强制转换-工作正常
doIntegerStuff(b.get());//checkcast的运行时错误
doStringStuff(b.get());//编译错误
}
公共静态void doStuff(对象){}
公共静态void doStringStuff(字符串整数){}
公共静态void doIntegerStuff(整数){}

我没有把这个问题理解为“我如何解决这个问题?”而是“为什么原始类型会以这种特殊的方式中断?”我假设
get
只会给你一个指向某个对象的指针,在你的示例中调用
toString
,但是
getClass
实际上会检查并解析该类型。您需要一个
整数
,但对象是一个
字符串
,因此
getClass
在内部强制转换它并失败。@GhostCat更清楚了@鬼猫去吧。我一点也不介意。谢谢你的邀请improvement@GhostCat是,它在第二个
get
中插入它,因为类型检查来自
getClass
。第一行不会引发异常,因为所有
对象
类型都实现了
toString
。您调用的任何试图解析类型的方法都将抛出异常。预期的返回类型为
Class
,当类声明为
时,返回
类将毫无意义,因此castwhy getClass()与get()不同,因为getClass()将在get()时执行强制转换不会施放,但只返回对象是什么?在本例中,尽管get()是根据声明返回一个整数,但它实际上返回了一个字符串而不会引起问题,而getClass()关心它返回的是什么类型?谢谢你的回答,我只是需要澄清一下。
System.out.println(b.get().getClass()); // error
  Box<Integer> b = new Box<>(new String("may be"));
 public static void main(String[] args) {
          Box<Integer> b = new Box(new String("may be"));
          doStuff(b.get()); // no checkcast needed - works fine
          doIntegerStuff(b.get()); // run-time error with checkcast
          doStringStuff(b.get()); // compile error
       }

 public static void doStuff(Object object){}
 public static void doStringStuff(String integer){}
 public static void doIntegerStuff(Integer integer){}