Java 当超类未实现接口但子类未实现时,在接口子类和超类之间强制转换
在下面的代码中Java 当超类未实现接口但子类未实现时,在接口子类和超类之间强制转换,java,inheritance,interface,casting,Java,Inheritance,Interface,Casting,在下面的代码中 abstract class Vehicle { } class Car extends Vehicle implements LandMover { } interface LandMover { } Car porsche=new Car(); LandMover lmv; lmv = porsche; Vehicle vec = (Vehicle)lmv; 第四行中是否应该有编译器错误,因为类车辆和接口LandMover之间没有关系
abstract class Vehicle { }
class Car extends Vehicle implements LandMover { }
interface LandMover { }
Car porsche=new Car();
LandMover lmv;
lmv = porsche;
Vehicle vec = (Vehicle)lmv;
第四行中是否应该有编译器错误,因为类车辆和接口LandMover之间没有关系??如果没有,原因可能是什么。谢谢 将出现错误,因为无法实例化抽象类 有关更多信息,请参阅此
编译器仅检查是否存在可能的关系,并且存在一种关系:
LandMover
可以是汽车
,而汽车又是一辆汽车
。由于您承诺使用显式强制转换可以进行此转换,因此编译器会很高兴。通过显式强制转换到车辆
,编译器不会告诉您任何信息。如果这些关系最终没有完全解决,并且您正在铸造一些实际上不是车辆的东西,那么您可能会在运行时遇到异常,因为
LandMover lmv = porsche;
不声明LandMover类型的对象,但通过引用“LandMover”引用“Car”类型的对象。编译器知道这是一个“Car”类型的对象(注意:“Car”和“Vehicale”在同一个继承树中)。编译可以使用您提供的代码。lmv=porsche;
与
public class Car extends Vehicle implements LandMover {
public static void main(String args[]){
LandMover car = new Car();
}
}
汽车实现了LandMover,因此您可以将其用作多态参考。因此,到目前为止没有问题
Vehicle vec = (Vehicle)lmv;
现在你说的是,LandMover(参考)很可能是一辆汽车,实际上是一辆汽车,所以编译器不会抱怨
但请注意,在该类型转换之后,如果您试图调用未在Vehicle类中定义的vec
上的某些函数(即使是在Car类中定义的函数,尽管实际上它是Car类的运行时实例),编译器将投诉。
这是因为在运行时编译器只检查引用类型的类,以及调用的函数是否已定义(可能未实现)在它里面就不会有任何编译错误。不会有任何编译错误。这是因为一个类可以实现许多接口,因此一个给定的“LandMover”实例可以是一个车辆。但是,由于一个类可以从一个超类继承,你知道你不能将“java.lang.String”强制转换为“Vehicle”,因为它们不是共享对象以外的公共超类。考虑层次结构
Car扩展车辆
&
Car实现陆地移动器
对于铸造vec=(Vehicle)lmv;
编译器可以静态地检查(编译时),lmv
的类型是LandMover
,反过来也是可以是Car
(正如Car实现LandMover
).现在,由于Car扩展了车辆
,编译器没有抱怨
要确认它,请尝试对代码进行如下注释
//Car porsche=new Car();
LandMover lmv;
//lmv= porsche;
Vehicle vec = (Vehicle)lmv; //Compiler error
在这里,编译器确信lmv
肯定不能成为Vehicle
,因此会标记错误。您尝试时发生了什么?@Kugathasan我尝试过,它没有显示任何编译错误,我现在对答案有点困惑他没有实例化一个抽象类。他实例化了子类,并使用了一个超类变量无法保存引用。编译失败,因为“lmv”未初始化。如果u set lmv=null,则它可以正常编译。它将出现运行时异常(类强制转换异常)它编译得很好,因为编译器认为抽象类载体有可能被另一个类扩展,正如kappil在上面解释的那样,expilcit casting不会给出任何编译错误