使用超类引用的java转换

时间:2011-11-22 03:37:02

标签: java casting

有人可以解释这里发生了什么吗?

假设CarBikeVehicle的子类。

我认为Vehicle v引用会被转换为Bike。我知道这是非法的,实际上编译器会吐出... Car cannot be cast to Bike

但是,Vehicle不应该被强制转换为Bike吗?毕竟,Vehicle vVehicle引用。

public class Test {
   public static void main(String[] args) {
       Vehicle v = new Car();
       Bike b = (Bike) v;
       // some stuff
    }   
}

5 个答案:

答案 0 :(得分:3)

错误消息显示Car,因为这是运行时异常。由于此时它知道Vehicle引用指向的实际实例(Car,Bike或Vehicle),因此它提供了更具体的错误消息。

如果在编译时这是一个异常,编译器会提到Vehicle,因为编译器可能不知道Vehicle引用指向的实际实例。

答案 1 :(得分:1)

它实际上是一个Carv的类型为Vehicle,因此Vehicle v = new Car();的分配有效,因为CarVehicle

对象v保留其身份;那是一个Car。因此非法演员阵容从CarBike

答案 2 :(得分:0)

该行

Bike b = (Bike) v;
如果v是传入的Vehicle,那么

将是合法的。所以我猜这个验证是在优化过程中发生的。如果可以的话,编译器想要优化掉正常的工作 - 甚至可能完全优化b - 当然,如果v被创建为{{>},可以 {1}}位于上一行,而不是Bike

答案 3 :(得分:0)

(半)普通英语回复:

汽车不能突然“变成”自行车或被视为自行车,因为自行车会有不同的属性(变量)描述它,以及交互的不同方式用它(方法)。

然而,它们都是车辆,因此它们会有一些共同点,例如,能够转向,向左或向右转,或换档。

当你有这样的逻辑时,这很简单:

ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>();
vehicles.add(new Bike());
vehicles.add(new Car());
vehicles.add(new Bike());

//Some other crazy code

for(Vehicle v : vehicles) {
    v.applyBrakes();
    v.changeDownGear();
    v.turnRight();
}

Vehicle(Bike,Car,Segway等)的每个子类都有自己的方法实现并适当处理自己

答案 4 :(得分:0)

如果没有源代码,就无法明确地说出什么是合法的,什么不是。但是,可以安全地假设这些类的继承树看起来像

    Vehicle
       |
  __________
  |         |
 Car      Bike

CarBikeVehicle的子类,这意味着VehicleCarBike的推广。在Java中,您可以将子类的实例强制转换为其基类。因此,在这种情况下,您可以将Car投射到车辆上并像对待实际拥有Vehicle对象的实例一样对待它。 Bike也是如此。但是,因为Car不是Bike的子类,所以不能从一个转换为另一个。所有Cars都是Vehicles,但并非所有Vehicles都是Cars。它们也不是BikesCar永远不是Bike,反之亦然。

您这样做是为了创建更具可扩展性的代码。例如,您可以编写能够理解如何与将来编写的代码进行交互的代码。一个例子是一些通用接口,例如drive(),允许其他开发人员稍后提供自定义实现。你的代码虽然事先编写,但仍可以使用它,因为它可以将新的子类视为基类的实例。