Java核心技術第五章——2.Object類

w39發表於2021-09-09

Object類:所有類的超類

Object類是Java中所有類的始祖,在Java中每個類都是由它擴充套件而來的。但是並不需要這樣寫:

public class Emloyee extends Object

如果沒有明確的指出超類,Object就被認為是這個類的超類。在Java中,只有基本資料型別不是物件,所有陣列型別,不管是物件陣列還是基本型別的陣列都擴充套件(繼承)了Object類。

 

1.equals方法

Object類中的equals方法用於檢車一個物件是否等於另外一個物件。也就是說是否具有相同的引用。當時這種判斷相同引用一般來說並沒有什麼luan用。一般只需要兩個物件的狀態相等,就認為這兩個物件時相等的。

圖片描述

public class Employee{

    private double salary;

    private LocalDate hireDay;

    public boolean equals(Object otherObject){
        if(this == otherObject) return true; //是否為相同引用

        if(otherObject==null) return false;

        if(this.getClass() != otherObject.getClass()) return false; //是否屬於同一個類
        Employee other = (Employee)otherObject;//例項化同一個類則強轉
        
        return salary==other.salary&&hireDay.equals(other.hireDay);//判斷值是否一致。
    }

}

圖片描述

 

2.相等測試與繼承

Java語言規範要求equals方法具有下面的特性:

1.自反性:對於任何非空引用x,x.equals(x)返回true

2.對稱性:對於任何引用x和y,當且僅當y.equals(x)返回true,x.equals(y)也應該返回true.

3.傳遞性:對於任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也應該返回true

4.一致性:如果x和y引用的物件沒有發生任何改變,返回撥用x.equals(y)應該返回同樣的結果。

5.對於任何的非空引用x,x.equals(null)應該返回false。

 

然而利用只getClass檢測,是不符合置換原則的。這是因為沒有任何一個子類需要重新定義集合是否相等的語義(重新定義equals方法)。在Object中的equals方法沒有被宣告為final,這樣做,可以讓子類選擇更加有效的演算法對集合進行是否相等的檢測(重寫equals方法)。

如果子類能夠擁有自己的相等概念(equals方法在子類中定義),則對稱性需求將強制採用getClass進行檢測。

如果由超類決定相等的概念(equals方法在父類中定義),那麼久可以使用instanceof進行檢測。這樣就可以在不同子類的物件之間進行相等的比較。(比較的域只能是父類的資料域)

 

一個比較完善的equals方法:

1.方法引數命名為otherObject 型別為Object,稍後用到。

2.判斷是否為同一引用,如果相同返回true。

3.判斷是否為Null,如果為Null則返回false;

4.判斷是否為同一個類或同一個父類,判斷是否為同一個類時則需要在每個子類中定義equals方法(使用getClass方法判斷)。

如果判斷是否為同一個父類,那麼相等時只能使用到父類的equals方法(使用instanceof方法)。

5.強制型別轉換otherObject引用為需要判斷的型別。

6.判斷基本資料型別域和物件域是否都一致。一致返回true.

 

3.hashCode方法

雜湊碼(hash code)是由物件匯出的一個整型值。雜湊碼是沒有規律的。如果x和y是兩個不同的物件,x.hashCode()和y.hashCode()基本上不會相同。例:

圖片描述

        String s = "OK";
        StringBuilder sb = new StringBuilder(s);
        System.out.println(s.hashCode() + "  " + sb.hashCode());

        String t = new String("OK");
        StringBuilder tb = new StringBuilder(t);
        System.out.println(t.hashCode() + "   " + tb.hashCode());

圖片描述

2524  1376400422
2524   418304857

此處s和t擁有相同的雜湊碼,這是因為字串的雜湊碼是由內容匯出的。即內容相同,hashCode值相同。

而StringBuffer類中沒有定義hashCode方法,是因為它的雜湊碼是由Object類的預設hashCode方法匯出的物件儲存地址。所以即物件不同,則hashCode值不同。

 

注意:如果重新定義Equals方法後,hashCode也必須重新定義。保證x.equals(y)返回true,x.hashCode就必須和y.hashCode()的值一致。

 

4.toString方法

在Objcet中有一個重要的方法,就是toString方法,它用於返回表示物件值得字串。而Objcet中的toString方法列印的是類名和雜湊碼值。一般比較少用。

 

   public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

 

而自定義的實體類,一般都會重寫toString方法。而重寫的toString方法用方括號把域值括起來。例:

    public String toString() {
        return getClass().getName()+"{" +
                "salary=" + salary +
                ", hireDay=" + hireDay +
                '}';
    }

如果是子類的程式設計師定義自己的toString方法,並將子域新增進去。那麼子類增加super.toString即可。

若類域包含陣列型別的。那麼使用toString方法將會把陣列列印成類名@雜湊碼。是因為陣列繼承了Object的toString方法。

解決方法:一維陣列使用Arrays.toString(陣列引用),多維陣列使用Arrays.deepToString(陣列引用)。

個人提倡使用lombok外掛。不需要寫set、get、toString方法。更詳細的lombok外掛解釋請自行上網搜尋。

原文出處:https://www.cnblogs.com/Johnson-lin/p/9404966.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/854/viewspace-2814024/,如需轉載,請註明出處,否則將追究法律責任。

相關文章