【问题标题】:Casting between interface sublass and superclass when superclass is not implementing interface but subclass is当超类未实现接口但子类实现时,在接口子类和超类之间进行转换
【发布时间】:2013-12-14 07:54:11
【问题描述】:

在下面的代码中

abstract class Vehicle { }
class Car extends Vehicle implements LandMover { }
interface LandMover { }
     Car porsche=new Car();
     LandMover lmv;
     lmv = porsche;
     Vehicle vec = (Vehicle)lmv;

第 4 行是否应该存在编译器错误,因为类车辆和接口 LandMover 之间没有关系?如果没有可能是什么原因。谢谢!!

【问题讨论】:

  • 你尝试的时候发生了什么?
  • @Kugathasan 我试过它没有显示任何编译错误,我现在对答案有点困惑

标签: java inheritance interface casting


【解决方案1】:

考虑层次结构

Car extends Vehicle

&

Car implements LandMover

对于转换Vehicle vec = (Vehicle)lmv;,编译器可以检查静态(编译时间),lmv 的类型是LandMover,而这又是 CANCar(如Car implements LandMover)。现在作为Car extends Vehicle,编译器不会抱怨。

确认它,尝试如下注释代码

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

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

【讨论】:

  • 如果您设置 lmv=null 编译正常,则由于 'lmv' 未初始化,因此编译失败。
  • 它会给出运行时异常(类转换异常)它编译得很好,因为编译器认为抽象类车辆有可能被另一个类扩展,并且因为 kappil 给出了上面的解释,显式转换不会给出任何编译错误
【解决方案2】:

不会有任何编译错误。这是因为一个类可以实现许多接口,因此给定的“LandMover”实例可以是车辆。但是,由于一个类可以从单个超类继承,因此您知道不能将“java.lang.String”转换为“Vehicle”,因为它们不共享对象以外的公共超类。

【讨论】:

    【解决方案3】:

    使用您提供的代码进行编译就可以了。 lmv = porsche;和说的一样

    public class Car extends Vehicle implements LandMover {
    
        public static void main(String args[]){
    
            LandMover car = new Car();
        }
    }
    

    A Car 实现了 LandMover,因此您可以将其用作多态引用。所以到目前为止没有问题。

    Vehicle vec = (Vehicle)lmv;
    

    现在你说的 LandMover(reference) 很可能是一辆汽车,实际上是一辆汽车。所以编译器不会抱怨。

    但请注意,如果您尝试在 vec 上调用未在 Vehicle 类中定义的某些函数(即使是 Car 类中的函数,尽管事实上它是 Car 类的运行时实例)编译器,请注意在这种类型转换之后会投诉。

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

    【讨论】:

      【解决方案4】:

      不,因为

          LandMover lmv = porsche;
      

      不声明 LandMover 类型的对象,而是通过引用“LandMover”引用“Car”类型的对象。编译器知道这是一个“Car”类型的对象(注意:“Car”和“Vehicale”在同一个继承树中)。

      【讨论】:

        【解决方案5】:

        通过显式转换为Vehicle,编译器不会告诉您任何信息。如果关系最终没有完全解决,并且您正在投射实际上不是Vehicle

        【讨论】:

          【解决方案6】:

          编译器只检查是否存在可能的关系,并且存在一个:

          LandMover 可以是 Car,而后者又是 Vehicle。由于您承诺使用显式强制转换可以进行此转换,因此编译器很高兴。

          【讨论】:

            【解决方案7】:

            抽象类无法实例化会报错 有关更多信息,请参阅此 post

            【讨论】:

            • 他没有实例化一个抽象类。他实例化了子类并使用超类变量来保存引用。
            猜你喜欢
            • 1970-01-01
            • 2020-03-02
            • 1970-01-01
            • 1970-01-01
            • 2023-03-17
            • 2017-10-21
            • 1970-01-01
            • 2018-06-29
            • 2019-03-11
            相关资源
            最近更新 更多