java 多态判断非空_Java核心技术(四):继承
本章目錄:
- 一、類、超類和子類
- 1.多態
- 2.動態綁定
- 3.阻止繼承:final類和方法
- 4.抽象類
- 5.訪問修飾符總結
- 二、Object類:所有類的父類
- 1.equals方法
- 2.hashcode方法
- 3.toString方法
- 三、對象包裝器與自動裝箱
- 四、反射
- 1.Class類
- 2.捕獲異常
- 3.利用反射分析類的能力
- 4.在運行時使用反射分析對象
一、類、超類和子類
- 子類繼承父類,二者之間是is-a關系,子類擁有父類的全部資源,并且可以添加特有的域和方法。
- 子類無法刪除。
- java不支持多繼承。
- 子類可重寫父類的方法,注意,重寫和方法重載是不同的概念。 在覆蓋(重寫)一個方法的時候,子類方法不能低于超類方法的可見性。特別是,如果超類方法是 public,子類方法一定要聲明為 public。
- 子類如何調用父類方法:super.父類方法名()。
- 子類構造器中如何調用父類構造器:super.父類名(參數列表),注意,這句代碼必須在子類構造器中的第一句。
如果超類沒有不帶參數的構造器,并且在子類的構造器中又沒有顯式地調用超類的其他構造器,則 Java 編譯器將報告錯誤。
- 多態:一個對象變量可以指示多種實際類型的現象被稱為多態。在運行時能夠自動地選擇調用哪個方法的現象稱為動態綁定。
1.多態
- 在 Java程序設計語言中,對象變量是多態的。一個父類變量既可以引用一個父類對象,也可以引用任何一個子類的對象。
- 然而,不能將一個父類的引用賦給子類變量。
- 警告∶ 在 Java中,子類數組的引用可以轉換成超類數組的引用,而不需要采用強制類型轉換。例如,下面是一個經理數組
2.動態綁定
前面已經說過了,一個對象變量可以指示多種實際類型的現象被稱為多態,在運行時能夠自動地選擇調用哪個方法的現象稱為動態綁定。
下面請看調用方法的過程:
- 編譯器查看對象的聲明類型和方法名。假設調用x.f(param),且隱式參數x聲明為C類的對象。需要注意的是∶ 有可能存在多個名字為f,但參數類型不一樣的方法。編譯器將會一一列舉所有C類中名為f的方法和其超類中訪問屬性為 public 且名為f的方法(超類的私有方法不可訪問)。至此,編譯器已獲得所有可能被調用的候選方法。
- 重載解析:接下來,編譯器將查看調用方法時提供的參數類型。如果在所有名為f的方法中存在一個與提供的參數類型完全匹配,就選擇這個方法。這個過程被稱為重載解析。由于允許類型轉換(int 可以轉換成 double,Manager類可以轉換成 Employee;類,等等),所以這個過程可能很復雜。如果編譯器沒有找到與參數類型匹配的方法,或者發現經過類型轉換后有多個方法與之匹配,就會報告一個錯誤。至此,編譯器已獲得需要調用的方法名字和參數類型。
- 如果是 private 方法、static方法、final方法或者構造器,那么編譯器將可以準確地知道應該調用哪個方法,我們將這種調用方式稱為靜態綁定。
- 當程序運行,并且采用動態綁定調用方法時,虛擬機一定調用與x所引用對象的實際類型最合適的那個類的方法。否則,將在D類的超類中尋找該方法,以此類推。
每次調用方法都要進行搜索,時間開銷相當大。因此,虛擬機預先為每個類創建了一個方法表,其中列出了所有方法的簽名和實際調用的方法。
這里需要提醒一點,如果調用super.f(param),編譯器將對隱式參數超類的方法表進行搜索。
3.阻止繼承:final類和方法
用 final修飾的類是禁止繼承的;用final修飾的方法,則表明該方法不允許類的子類重寫;final類中的所有方法默認為是final方法。
在早期的Java中,有些程序員為了避免動態綁定帶來的系統開銷而使用final關健字。如果一個方法沒有被覆蓋并且很短,編譯器就能夠對它進行優化處理,這個過程為稱為內聯。例如,內聯調用e.getName()將被替換為訪問e.name域。然而,如果getName()在另外一個類中被覆蓋,那么編譯器就無法知道覆蓋的代碼將會做什么操作,因此也就不能對它進行內聯處理了。
幸運的是,虛擬機中的即時編譯器比傳統編譯器的處理能力強得多。這種編譯器可以準確地知道類之間的繼承關系,并能夠檢測岀類中是否真正地存在覆蓋給定的方法。如果方法很簡短、被頻繁調用且沒有真正地被覆蓋,那么即時編譯器就會將這個方法進行內聯處理。如果虛擬機加載了另外一個子類,而在這個子類中包含了對內聯方法的覆蓋,那么將會發生什么情況呢?優化器將取消對覆蓋方法的內聯。這個過程很慢,但卻很少發生。
4.抽象類
為了提高程序的清晰度,包含一個或多個抽象方法的類本身必須被聲明為抽象的。
abstract class Person{……public abstract String getDescription(); }- 除了抽象方法之外,抽象類還可以包含具體數據和具體方法。但盡量使得抽象類中不包含具體方法。
- 抽象方法充當著占位的角色,它們的具體實現在子類中。不過,在子類中定義部分抽象方法或抽象方法也可以不定義,這樣就必須將子類也標記為抽象類。
- 類即使不含抽象方法,也可以將類聲明為抽象類。
- 抽象類不能被實例化;可以定義一個抽象類的對象變量,但是它只能引用非抽象子類的對象。
5.訪問修飾符總結
- 對本類可見private
- 對所有類可見public
- 對本包和所有子類可見protected
- 默認本包可見
二、Object類:所有類的父類
可以使用Object類型的變量引用任何類型的對象。
1.equals方法
檢測一個對象和另一個對象是否相等,用于判斷兩個對象是否具有相同的引用。
在子類中定義 equals 方法時,首先調用超類的 equals。如果檢測失敗,對象就不可能相等。如果超類中的域都相等,就需要比較子類中的實例域。
Java中的equals方法具有以下特性:
- 自反性∶ 對于任何非空引用x,x.equals(x)應該返回 true。
- 對稱性∶ 對于任何引用x和y,當且僅當yequals(x)返回true,x.equals(y)也應該返回 true。如果x和y不屬于同個類,可能不適用。
- 傳遞性∶對于任何引用x、y和z,如果x.cquals(y)返回true,yequals(z)返回true, x.equals(z)也應該返回 true。
- 一致性∶如果x和y引用的對象沒有發生變化,反復調用x.equals(y)應該返回同樣的結果。
- 對于任意非空引用x,x.equals(null)應該返回 false。
2.hashcode方法
散列碼是由對象導出的一個整型值。散列碼是沒有規律的。如果x和y是兩個不同的對象,x.hashCode()與y.hashCode()基本上不會相同。在表5-1中列出了幾個通
3.toString方法
三、對象包裝器與自動裝箱
- 對象包裝器:
所有的基本類型都有一個與之對應的類。這些類稱為包裝器∶Integer、Long、Float、Double、Short、Byte、Character、Void和 Boolean(前 6個類派生于公共的超類 Number)。對象包裝器類是不可變的,即一旦構造了包裝器,就不允許更改包裝在其中的值。同時,對象包裝器類還是 final,因此不能定義它們的子類。
泛型是能是引用類型而不能是基本類型。
- 自動裝箱:
list是一個集合對象,list.add(3)將自動地變換成list.add(Integer.valueOf(3)。這一過程就是自動裝箱。
int n= list.get(i)將自動被翻譯成int n=list.get(i).intValue()。這一過程就是自動拆箱。
最后強調一下,裝箱和拆箱是編譯器認可的,而不是虛擬機。編譯器在生成類的字節碼時,插入必要的方法調用。虛擬機只是執行這些字節碼。
四、反射
1.Class類
在程序運行期間,保存對象的運行時類型信息的類被稱為 Class。
Employee e;……Class c1=e.getClass();//獲取Class對象String classType=c1.getName();//獲取e的類名,包含了包前綴String name=e.getName();//獲取e的對象名Class c2=Class.forName(classType);//也可通過已知的類名獲取Class對象Class c3=Date.class;//也可通過這種方式獲取類對象Class c4=int.class;CLass c5=Double[].class;Object o=e.getClass().new Instance();//創建一個和e同類型的實例,調用的是默認構造器2.捕獲異常
try{//可能拋出異常的語句}catch(Exception e){//處理器語句}一旦try中出現異常,將跳過剩余的部分,直接進入catch中進行處理;若try中沒有出現異常,則跳過catch中的部分。
3.利用反射分析類的能力
說白了就是通過調用Class類中的方法得到關于所涉及對象的域、方法、構造器、訪問權限修飾符相關的信息,這部分學習下Java API中有關Class的部分就好。
4.在運行時使用反射分析對象
在代碼運行時獲取到對象的狀態等。好好看看API。
總結
以上是生活随笔為你收集整理的java 多态判断非空_Java核心技术(四):继承的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: easyexcel多个sheet导入_J
- 下一篇: 未来计算机作文1000字,未来的生活作文