天天看點

再談 Java 的繼承和超類 Object(2)

02、

在 Java 中,所有類都由 Object 類繼承而來。Object 這個單詞的英文意思是對象,是不是突然感覺頓悟了——萬物皆對象?沒錯,Java 的設計者真是良苦用心了啊!現在,你一定明白了為什麼 Java 是面向對象程式設計語言的原因。

你可能會疑惑地反問道:“我的類明明沒有繼承 Object 類啊?”如果一個類沒用顯式地繼承某一個類,那麼它就會隐式地繼承 Object 類。換句話說,不管是雞生了蛋,還是蛋孵出了雞,總有一隻 Object 雞或者一個 Object 蛋。

在面試的時候,你可能會被問到這麼一個問題:“Object 類包含了哪些方法呢?”

1)protected Object clone() throws CloneNotSupportedException 建立并傳回此對象的副本。

不過,《阿裡巴巴 Java 開發手冊》上建議:慎用 Object 的 clone 方法來拷貝對象。因為 Object 的 clone 方法預設是淺拷貝,如果想實作深拷貝需要重寫 clone 方法實作屬性對象的拷貝。

什麼是淺拷貝,什麼是深拷貝呢?

淺拷貝是指在拷貝對象時,會對基本資料類型的變量重新複制一份,而對于引用類型的變量隻拷貝了引用,并沒有對引用指向的對象進行拷貝。

深拷貝是指在拷貝對象時,同時對引用指向的對象進行拷貝。

淺拷貝和深拷貝的差別就在于是否拷貝了對象中的引用變量所指向的對象。

2)public boolean equals(Object obj) 判斷另一對象與此對象是否「相等」。

該方法使用的區分度最高的“==”操作符進行判斷,是以隻要兩個對象不是同一個對象,那麼 equals() 方法一定傳回 false。

《阿裡巴巴 Java 開發手冊》上強調:由于 Object 的 equals 方法容易抛出空指針異常,是以應該使用常量或者确定不為 null 的對象來調用 equals。

正例:"test".equals(object);object.equals("test");

在正式的開發項目當中,最經常使用該方法進行判斷的就是字元串。不過,建議使用org.apache.commons.lang3.StringUtils,不用擔心出現空指針異常。具體使用情況如下所示:

StringUtils.equals(null, null)   = true

StringUtils.equals(null, "abc")  = false

StringUtils.equals("abc", null)  = false

StringUtils.equals("abc", "abc") = true

StringUtils.equals("abc", "ABC") = false

3)public native int hashCode() 傳回此對象的哈希碼。hashCode() 是一個 native 方法,而且傳回值類型是整形;實際上,該方法将對象在記憶體中的位址作為哈希碼傳回,可以保證不同對象的傳回值不同。

A native method is a Java method whose implementation is provided by non-java code.native 方法是一個 Java 調用非 Java 代碼的接口。該方法的實作由非 Java 語言實作,比如 C。這個特征并非 Java 所特有,其它的程式設計語言也有這個機制,比如 C++。

hashCode() 通常在哈希表中起作用,比如 HashMap。

向哈希表中添加 Object 時,首先調用 hashCode() 方法計算 Object 的哈希碼,通過哈希碼可以直接定位 Object 在哈希表中的位置。如果該位置沒有對象,可以直接将 Object 插入該位置;如果該位置有對象,則調用 equals() 方法比較這個對象與 Object 是否相等,如果相等,則不需要儲存 Object;如果不相等,則将該 Object 加入到哈希表中。

4)protected void finalize() throws Throwable 當垃圾回收機制确定該對象不再被調用時,垃圾回收器會調用此方法。不過,fnalize 機制現在已經不被推薦使用,并且在 JDK 9 開始被标記為 deprecated(過時的)。

5)public final Class getClass() 傳回此對象的運作時類。

當我們想知道一個類本身的一些資訊(比如說類名),該怎麼辦呢?這時候就需要用到 Class 類,該類包含了與類有關的資訊。請看以下代碼:

Wanger wanger = new Wanger();

Class c1 = wanger.getClass();

System.out.println(c1.getName());

// 輸出 Wanger

6)public String toString() 傳回此對象的字元串表示形式。

《阿裡巴巴 Java 開發手冊》強制規定:POJO 類必須重寫 toString 方法;可以使用 Eclipse 直接生成,點選 「Source」→「Generate toString」。示例如下:

class Wanger {

   private Integer age;

   @Override

   public String toString() {

       return "Wanger [age=" + age + "]";

   }

}

重寫 toString() 有什麼好處呢?當方法在執行過程中抛出異常時,可以直接調用 POJO 的 toString() 方法列印其屬性值,便于排查問題。

POJO(Plain Ordinary Java Object)指簡單的 Java 對象,也就是普通的 JavaBeans,包含一些成員變量及其 getter / setter ,沒有業務邏輯。有時叫做 VO (value - object),有時叫做 DAO (Data Transform Object)。

03、

本篇,我們先談了面向對象的重要特征繼承;然後談到了繼承的終極父類 Object!