当超类没有实现接口但子类实现接口时,在接口子类和超类之间进行转换

4
在下面的代码中:
abstract class Vehicle { }
class Car extends Vehicle implements LandMover { }
interface LandMover { }
     Car porsche=new Car();
     LandMover lmv;
     lmv = porsche;
     Vehicle vec = (Vehicle)lmv;

第四行应该会有编译错误,因为类vehicle和接口LandMover之间没有关系吗?如果没有错误,可能的原因是什么?谢谢!


当你尝试时发生了什么? - Abimaran Kugathasan
@Kugathasan 我已经尝试过了,没有显示任何编译错误,现在对答案有点困惑。 - unknown
7个回答

6
编译器只检查是否存在可能的关系,事实上是有这样一个关系:一个 LandMover 可以是一辆 Car,而这个 Car 又 IS-A Vehicle。由于您使用了显式转换来保证这种转换是可行的,因此编译器很开心。

1
不,因为


    LandMover lmv = porsche;

该代码并未声明一个类型为LandMover的对象,而是通过引用'LandMover'来引用类型为'Car'的对象。编译器知道这是一个'Car'类型的对象(注意:'Car'和'Vehicale'在同一继承树中)。


0
编译会通过你提供的代码。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类的运行时实例),编译器将会抱怨。

这是因为在运行时,编译器仅检查引用类型的类,如果调用的函数在其中定义(可能未实现),则不会有任何编译错误。


0

考虑到继承关系

汽车继承自交通工具

&

汽车实现LandMover

对于强制类型转换 Vehicle vec =(Vehicle)lmv; 编译器可以在静态(编译时)检查lmv的类型,该类型是LandMover,而LandMover可以Car(因为Car实现LandMover)。由于Car扩展Vehicle,因此编译器不会发出投诉。

为了确认它,请尝试按以下方式注释代码

        //Car porsche=new Car();
         LandMover lmv;
         //lmv= porsche;
         Vehicle vec = (Vehicle)lmv; //Compiler error

在这里,编译器确定 lmv 绝对不可能是 Vehicle,因此会标记错误。


1
编译失败是因为 'lmv' 没有被初始化,如果你将 lmv 设置为 null,它就可以成功编译。 - Dev Blanked
它会抛出运行时异常(类转换异常),编译器认为抽象类vehicle可能被另一个类继承,因此编译通过,正如kappil在上面给出的解释一样,显式转换不会产生任何编译错误。 - unknown

0

通过显式地进行类型转换到 Vehicle,编译器不会告诉你任何信息。如果关系最终不完全符合要求并且你将某些实际上不是 Vehicle 的内容转换,你只能在运行时获取异常。


0

不会出现编译错误。这是因为一个类可以实现多个接口,因此给定的“LandMover”实例可以是Vehicle。但是,由于一个类只能继承自一个超类,所以你知道你不能将“java.lang.String”强制转换为“Vehicle”,因为它们没有共同的超类,除了Object。


-1

由于抽象类无法实例化,因此会出现错误 更多信息请参见 post


他没有实例化一个抽象类。他实例化了子类并使用超类变量保存引用。 - jantristanmilan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接