Java筆記: Casting 形態轉換

今天看到一個覺得非常有趣的程式,嘻嘻!

有一個程式碼的內容是這樣
class Animal {}
class Dog extends Animal{ }
public class CastTest {
 public static void main(String[] args) {
  Animal animal = new Animal();
  Dog d = (Dog) animal;
  String s = (String) animal;
 }
}
目測這隻程式毫無疑問的,它是錯的不能編譯,因為下面這兩行的cast形態不符
  Dog d = (Dog) animal;
  String s = (String) animal;
不過若我將第二個會發生錯誤的去除,結果竟然是這隻程式可以編譯了,但是執行時丟出了ClassCastException,人覺得這應該是可以直接判斷出來的結果,但是為什麼不會在編譯時期查出來?

Upcasting & Downcasting

Upcasting 由子類別轉換為父類別
這種轉換是可以立即被Compiler察覺的,利用繼承樹馬上就可以判斷是否子類別是否是繼承自父類別。 這個部分可以說是多型(Polymorphism)的利用,此外,upcasting是隱式轉換Compiler會自動進行轉換。

Downcasting 由父類別轉換為子類別
這種轉換沒有辦法馬上知道最後的結果,只能判斷是否在同一個繼承樹,其他就必須在runtime才會知道,最常見的例子就是寫GUI時。
public void actionPerformed(ActioEvent e){
 Object s = e.getSource();
 if (s instanceof JButton) {
  JButton btn = (JButton)s;
  ....
 } else if (s instancef JList) {
   JList lst = (JList)s;
   ....
 }
}
產生事件的物件,並不能在編譯時期就能決定,只有在Runtime才能決定,不過編譯器還是會檢查繼承樹,在這個例子中,父類別是Object,Downcast成兩種JButton、JList,在Java中任何物件都繼承自Object,所以父類別與子類別一定在同一個繼承樹上,進而使得Object類別的downcasting轉換在compile time時一定會成功,因此在編譯時就不會產生錯誤。

結語
知道Downcasting與upcasting差別以後,就能知道最前面的例子,為何會產生這樣的結果,不過這種問題我還現在才知道,虧我已經用Java不短的一段時間了。

參考資料
SCJP Sun certified programmer for Java 5 : study guide (exam 310-055)
Java 程式語言教學:繼承

留言