五、java多型語法機制
class Animal { public void move() { System.out.println("動物移動"); } } class Cat extends Animal{ @Override public void move() { System.out.println("貓在移動"); } // 子類物件特有的行為/動作 public void fun() { System.out.println("貓抓老鼠"); } } class Bird extends Animal { @Overridepublic void move() { System.out.println("鳥在飛"); } public void fly() { System.out.println("Bird Fly"); } }
1.向上轉型和向下轉型的概念
1.1向上轉型(upcasting):
子型別-->父型別。又被稱為自動型別轉換。如:Animal a = new Cat();
1.2向下轉型(downcasting):
父型別-->子型別。又被稱為:強制型別轉換。【需要加強制型別轉換符】如:Cat c = (Cat)a;
什麼時候必須向下轉型:需要呼叫或者執行子類特有的方法。必須向下轉型才可以呼叫。
向下轉型存在風險,容易出現ClassCastException(型別轉換異常)
instanceof運算子:
可以在程式執行階段動態的判斷某個引用指向的物件是否為某一種型別。建議在向下轉型時使用instanceof執行符進行判定。(具體內容在下面)
無論向下/向上轉型,兩種型別之間必須要有繼承關係。沒有繼承關係,編譯不通過。
2.編譯階段和執行階段
Animal a = new Cat();//向上轉型 a.move();
2.1、java程式永遠都分為編譯階段和執行階段。
2.2、先分析編譯階段,再分析執行階段,編譯無法通過,根本無法執行。
2.3、編譯階段編譯器檢查a這個引用的資料型別為Animal,由於Animal.class位元組碼當中有move()方法,所以編譯通過了。這個過程稱為靜態繫結,編譯階段繫結。只有靜態繫結成功之後才有後續的執行。
2.4、在程式執行階段,JVM堆記憶體當中建立的物件是Cat物件,那麼a.move();在執行階段一定會呼叫Cat物件的move()方法,此時發生了程式的動態繫結,執行階段繫結。
2.5、無論是Cat類有沒有重寫move方法,執行階段一定呼叫的是Cat物件的move方法,因為底層真實物件就是Cat物件。
2.6、父型別引用指向子型別物件這種機制導致程式在編譯階段繫結和執行階段繫結兩種不同的形態/狀態,這種機制可以成為一種多型語法機制。
Animal a = new Cat(); a.fun();//此行報錯
此行程式碼報錯原因:
因為編譯階段編譯器檢查到a的型別是Animal型別,從Animal.class位元組碼檔案當中查詢fun()方法,最終沒有找到該方法,導致靜態繫結失敗,沒有繫結成功,編譯失敗。
解決方法:向下轉型,讓上面a物件執行fun()方法
a是無法直接呼叫的,因為a的型別Animal,Animal中沒有fun()方法。這時需要將a強制型別轉換為Cat型別。
a的型別是Animal(父類),轉換成Cat型別(子類),被稱為向下轉型。
Cat a2 = (Cat)a;
a2.fun();
3.向下轉型
Animal a3 = new Bird(); Cat c3 = (Cat)a3;//向下轉型
1.以上程式碼編譯沒有問題,因為編譯器檢查到a3的資料型別是Animal,Animal和Cat之間存在繼承關係,並且Animal是父型別,Cat是子型別,父型別轉換成子型別叫做向下轉型,語法沒有問題。
2.程式雖然編譯通過了,但是程式在執行階段會出現異常,因為JVM堆記憶體當中真實存在的物件是Bird型別,Bird物件無法轉換成Cat物件,因為兩種型別之間不存在繼承關係,出現異常java.lang.ClassCastException,型別轉換異常,這種異常總是在“向下轉型的時候”會發生。
2.instanceof運算子
2.1語法格式:(引用 instanceof 資料型別名 )
2.2以上運算子的執行結果型別是boolean型別。
2.3關於結果true/false
假設:(a instanceof Animal)
true表示:a這個引用指向的物件是一個Animal型別;
false表示:a這個引用指向的物件不是一個Animal型別。
Animal a3 = new Bird(); if(a3 instanceof Cat) { Cat c3 = (Cat)a3; c3.fun(); }else if(a3 instanceof Bird) { Bird b2 = (Bird)a3; b2.fly(); }
4.多型的作用:
降低程式的耦合度,提高程式的擴充套件力。
降低程式的耦合度【解耦合】,提高程式的擴充套件力。
提倡面向抽象程式設計,不要面向具體程式設計。
下一篇:持續更新中