2011-11-22 56 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(),它允許其他開發人員稍後提供自定義實現。儘管如此,你的代碼仍然可以用於它,因爲它可以將新的子類視爲基類的實例。