2011-11-22 64 views
5

有人可以解释这里发生了什么吗?带超类的java铸造参考

假设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 
    } 
} 
+1

因为JVM在抛出异常时知道它是Car。 –

+0

编译器不分割异常。该代码抛出**运行时**'ClassCastException'。 –

+0

@怀孕妈妈,如果您对其中的任何人都满意,请接受答案。 – Reddy

回答

3

错误消息说Car,因为这是运行时异常。由于此时它知道车辆参考指向的实际实例(汽车,自行车或车辆),因此它会给出更具体的错误消息。

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

+0

有道理!谢谢。 – m0therway

1

它实际上是一个Car正在施放。 vVehicle的类型,所以Vehicle v = new Car();的作业是CarVehicle

对象v保留其身份;那是一个Car。所以非法演员是从CarBike

0

线

Bike b = (Bike) v; 

将是法律如果说,v是在传入Vehicle。所以我想这个验证发生在优化过程中。如果可以的话,编译器要优化掉正常的工作 - 甚至可以完全优化b - 当然,如果v已在上一行而不是Car上创建为Bike,那么它当然可以可以

+0

只是为了迂腐,当且仅当v是Bike对象(或者子类的实例)时,该行才有效,而不管v对象来自何处。 –

0

A(半)通俗英语响应:

汽车不能突然“成为”自行车或像自行车被处理,因为一个自行车将具有不同的特性(变量)描述它,而不同的方法与之交互(方法)。

然而,它们都是车辆,所以它们会有一些共同的东西,例如,可以转向,左转或右转,或换档。

这使得简单,当你有一个像这样的逻辑:

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(); 
} 

车辆(自行车,汽车,赛格威等)的每个子类必须自己实现这些方法和适当地处理自己

0

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

Vehicle 
     | 
    __________ 
    |   | 
Car  Bike 

这样CarBikeVehicle子类,这意味着VehicleCarBike的推广。在Java中,您可以将一个子类的实例转换为它的基类。因此,在这种情况下,您可以将Car投射到车辆上,并将其视为您实际上拥有Vehicle物体的实例。 Bike也是如此。但是,因为Car不是Bike的子类,所以不能从一个投射到另一个。所有Cars均为Vehicles,但并非全部Vehicles均为Cars。它们也不是Bikes。并且Car从不是Bike,反之亦然。

您这样做是为了创建更具扩展性的代码。例如,您可以编写能够理解如何与将来编写的代码进行交互的代码。这方面的一个例子就是一些常见的界面,例如drive(),它允许其他开发人员稍后提供自定义实现。尽管如此,你的代码仍然可以用于它,因为它可以将新的子类视为基类的实例。