Dog d = (Dog)Animal; //Compiles but fails at runtime
在這裏,你對編譯器說:「相信我。我知道d
真的指的是Dog
對象」,但事實並非如此。 記得編譯器是被迫當我們做一個沮喪的信任我們。
編譯器只知道聲明的引用類型,JVM在運行時知道對象究竟是什麼。
因此,當在運行時的JVM出這個Dog d
實際上是指一個Animal
而不是Dog
對象,它說。 嘿......你對編譯器撒謊了,並且拋出了一個大胖子ClassCastException
。
所以,如果你是向下傾斜,你應該使用instanceof
測試,以避免搞砸。
現在,一個問題涉及到我們的心靈。爲什麼地獄編譯器在最終拋出一個java.lang.ClassCastException
時允許downcast?
答案是,所有的編譯器可以做的是驗證兩種類型在同一個繼承樹,所以這取決於什麼代碼可能已經來過了就垂頭喪氣 ,它可能是animal
是dog
類型。
編譯器必須允許可能在運行時工作的東西。
考慮下面的一小段代碼片段:
public static void main(String[] args)
{
Dog d = getMeAnAnimal();// ERROR: Type mismatch: cannot convert Animal to Dog
Dog d = (Dog)getMeAnAnimal(); // Downcast works fine. No ClassCastException :)
d.eat();
}
private static Animal getMeAnAnimal()
{
Animal animal = new Dog();
return animal;
}
但是,如果編譯器是確保投將無法工作,編譯將失敗。 I.E.如果試圖投在不同的繼承對象層次結構
String s = (String)d; // ERROR : cannot cast for Dog to String
不像向下轉換,上溯造型作品含蓄,因爲當你上溯造型你都隱含限制方法的數量,您可以調用, 因爲對面向下轉型,這意味着稍後您可能需要調用更具體的方法。
Dog d = new Dog(); Animal animal1 = d; // Works fine with no explicit cast Animal animal2 = (Animal) d; // Works fine with n explicit cast
上述兩個向上轉型將正常工作,沒有任何異常,因爲狗是-A的動物,anithing的動物可以做到,一隻狗能做到。但這不是真的,反之亦然。
您正在告訴編譯器不檢測錯誤。 – Mauricio 2011-02-01 13:14:02