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不会给出任何编译错误