Java继承转换运行时错误与编译器错误 问题
考虑下面的代码Java继承转换运行时错误与编译器错误 问题,java,inheritance,casting,compiler-errors,runtime-error,Java,Inheritance,Casting,Compiler Errors,Runtime Error,考虑下面的代码B继承自A,并且没有一个继承自String 我想知道以下问题的答案: 为什么第一个演员是B b1=(B)a1,是否生成运行时错误 为什么第一个第二个演员是,stringb1=(String)a1,是否生成编译错误 为什么会有区别?为什么编译器在第一种情况下看不到问题 代码 类A: public class A {} 和类B: public class B extends A {} 为什么第一个演员B b1=(B)a1;,是否产生运行时错误 A类型的变量可以存储B的实例。但是
B
继承自A
,并且没有一个继承自String
我想知道以下问题的答案:
stringb1=(String)a1代码>,是否生成编译错误
A
:
public class A {}
和类B
:
public class B extends A {}
A
类型的变量可以存储B
的实例。但是,并非所有A
的实例都是B
的实例
A
不是B
,而是B
是A
。(比如,并非所有动物都是狗,但狗是动物)
A
不是String
的超类型,String
也不是B
的超类型
A
类型的变量可以存储B
的实例;但是A
类型的变量永远不能存储String
的实例
A
类型的变量可以存储B
的实例。但是,并非所有A
的实例都是B
的实例
A
不是B
,而是B
是A
。(比如,并非所有动物都是狗,但狗是动物)
A
不是String
的超类型,String
也不是B
的超类型
因为
A
类型的变量可以存储B
的实例;但是A
类型的变量永远不能存储String类型A
的变量实际上可以是B
类型,因为B扩展了A。但是A
类型的变量永远不能是String
类型。这就是为什么编译器可以捕获对String
的转换,但不能捕获对B
的转换类型A
的变量实际上可以是B
类型,因为B扩展了A。但是A
类型的变量永远不能是String
类型。这就是为什么编译器可以捕捉到对字符串的转换,但不能捕捉到对B
的转换
为什么第一个演员B b1=(B)a1;,是否产生运行时错误
因为a1
是A
的实例,但与B
不兼容。具体来说,newa()
创建的对象与A
的子类不兼容。如果对象的运行时类(即调用new
的类)与目标类不同或不是目标类的子类,则在运行时转换到该目标类将失败。这仅仅是因为子类与该对象无关
为什么第一个第二个字符串b1=(字符串)a1;,是否产生编译错误
即使实际的强制转换发生在运行时,编译器也会执行类型检查并防止像这样的无意义操作。在这种情况下,将A
对象强制转换为String
是毫无意义的,编译器可以检测到它:String
和A
之间没有关系,编译器知道哪个类是其他类的子类。编译器知道在Java中,a1
不能成为String
或String
的子类的实例,这是因为String
不是a
的父类,后者是a1
的声明类型。也有例外情况,例如当开始对接口进行转换时
为什么会有区别?为什么编译器在第一种情况下看不到问题
编译器仅基于静态类型(变量或表达式的类型)验证类型强制转换。它不查看runtime类,当然,在运行时实际创建对象之前,runtime类是不可用的。当它能够确定强制转换不可能有效时(例如在第二种情况下),它将失败。在第一种情况下,从A
转换到B
可以通过编译,因为声明的类型是兼容的(即A
对象可能是B
的实例,编译器将其留给运行时检查实际对象)。在第二种情况下,编译器知道A
对象永远不能是String
的实例(因为String
不在A
的类型层次结构中,这在运行时不会改变)
为什么第一个演员B b1=(B)a1;,是否产生运行时错误
因为a1
是A
的实例,但与B
不兼容。具体来说,newa()
创建的对象与A
的子类不兼容。如果对象的运行时类(即调用new
的类)与目标类不同或不是目标类的子类,则在运行时转换到该目标类将失败。这仅仅是因为子类与该对象无关
为什么第一个第二个字符串b1=(字符串)a1;,是否产生编译错误
即使实际演员
public class B extends A {}