Java™ 教程(Object作為超類)

博弈發表於2019-01-19

Object作為超類

java.lang包中的Object類位於類層次結構樹的頂部,每個類都是Object類的直接或間接的後代,你使用或編寫的每個類都繼承Object的例項方法,你不需要使用任何這些方法,但是,如果你選擇這樣做,你可能需要使用特定於你的類的程式碼重寫它們,本節中討論的從Object繼承的方法是:

  • protected Object clone() throws CloneNotSupportedException
    建立並返回此物件的副本。
  • public boolean equals(Object obj)
    指示某個其他物件是否“等於”此物件。
  • protected void finalize() throws Throwable
    垃圾回收器在物件上執行垃圾回收時呼叫。
    集合確定不再有對該物件的引用。
  • public final Class getClass()
    返回物件的執行時類。
  • public int hashCode()
    返回物件的雜湊碼值。
  • public String toString()
    返回物件的字串表示形式。

ObjectnotifynotifyAllwait方法都在同步程式中獨立執行的執行緒的活動中發揮作用,這將在後面的課程中討論,這裡不討論,有五個方法:

  • public final void notify()
  • public final void notifyAll()
  • public final void wait()
  • public final void wait(long timeout)
  • public final void wait(long timeout, int nanos)

注意:許多方法都有一些微妙的方面,尤其是clone方法。

clone()方法

如果某個類或其中一個超類實現了Cloneable介面,則可以使用clone()方法從現有物件建立副本,要建立克隆,請編寫:

aCloneableObject.clone();

Object的此方法實現檢查呼叫clone()的物件是否實現Cloneable介面,如果物件沒有,則該方法丟擲CloneNotSupportedException異常,稍後的課程將介紹異常處理,目前,你需要知道clone()必須宣告為:

protected Object clone() throws CloneNotSupportedException

public Object clone() throws CloneNotSupportedException

如果要編寫clone()方法來覆蓋Object中的方法。

如果呼叫clone()的物件確實實現了Cloneable介面,物件的clone()方法實現建立與原始物件相同的類的物件,並初始化新物件的成員變數,使其具有與原始物件的相應成員變數相同的值。

使類可克隆的最簡單方法是將implements Cloneable新增到類的宣告中,然後你的物件可以呼叫clone()方法。

對於某些類,Objectclone()方法的預設行為可以正常工作,但是,如果一個物件包含對外部物件的引用,比如說ObjExternal,則可能需要重寫clone()以獲得正確的行為,否則,一個物件對ObjExternal所做的更改也將在其克隆中可見,這意味著原始物件及其克隆不是獨立的 — 要將它們分離,你必須重寫clone()以便它克隆物件和ObjExternal,然後原始物件引用ObjExternal,並且克隆引用ObjExternal的克隆,以便物件及其克隆真正獨立。

equals()方法

equals()方法將兩個物件進行相等性比較,如果它們相等則返回trueObject類中提供的equals()方法使用標識運算子(==)來確定兩個物件是否相等。對於原始資料型別,這會給出正確的結果,但是,對於物件,它沒有,Object提供的equals()方法測試物件引用是否相等 — 即,如果比較的物件是完全相同的物件。

要測試兩個物件在等價意義上是否相等(包含相同的資訊),必須重寫equals()方法,以下是重寫equals()Book類的示例:

public class Book {
    ...
    public boolean equals(Object obj) {
        if (obj instanceof Book)
            return ISBN.equals((Book)obj.getISBN()); 
        else
            return false;
    }
}

考慮這段程式碼來測試Book類的兩個例項是否相等:

// Swing Tutorial, 2nd edition
Book firstBook  = new Book("0201914670");
Book secondBook = new Book("0201914670");
if (firstBook.equals(secondBook)) {
    System.out.println("objects are equal");
} else {
    System.out.println("objects are not equal");
}

即使firstBooksecondBook引用了兩個不同的物件,此程式也顯示對objects are equal,它們被認為是相同的,因為比較的物件包含相同的ISBN號。

如果標識運算子不適合你的類,則應始終重寫equals()方法。

注意:如果重寫equals(),則還必須重寫hashCode()

finalize()方法

Object類提供了一個回撥方法finalize(),當它變為垃圾時,可以在物件上呼叫它,Objectfinalize()實現什麼也沒做 — 你可以重寫finalize()來執行清理,例如釋放資源。

finalize()方法可以由系統自動呼叫,但是什麼時候呼叫,或者即使呼叫,也是不確定的,因此,你不應該依賴此方法為你進行清理。例如,如果在執行I/O後沒有在程式碼中關閉檔案描述符,並且你希望finalize()為你關閉它們,則可能會耗盡檔案描述符。

getClass()方法

你不能重寫getClass

getClass()方法返回一個Class物件,該物件具有可用於獲取有關類的資訊的方法,例如其名稱(getSimpleName()),其超類(getSuperclass())及其實現的介面(getInterfaces()),例如,以下方法獲取並顯示物件的類名:

void printClassName(Object obj) {
    System.out.println("The object`s" + " class is " +
        obj.getClass().getSimpleName());
}

java.lang包中的Class類有很多方法(超過50個),例如,你可以測試以檢視類是註解(isAnnotation()),介面(isInterface())還是列舉(isEnum()),你可以檢視物件的欄位是什麼(getFields())或其方法是什麼(getMethods()),等等。

hashCode()方法

hashCode()返回的值是物件的雜湊碼,它是十六進位制的物件的記憶體地址。

根據定義,如果兩個物件相等,則它們的雜湊碼也必須相等,如果重寫equals()方法,則更改了兩個物件的等效方式,並且ObjecthashCode()實現不再有效,因此,如果重寫equals()方法,則還必須重寫hashCode()方法。

toString()方法

你應該始終考慮重寫你的類中的toString()方法。

ObjecttoString()方法返回物件的String表示,這對除錯非常有用,物件的String表示完全取決於物件,這就是你需要在類中重寫toString()的原因。

你可以使用toString()System.out.println()來顯示物件的文字表示形式,例如Book的例項:

System.out.println(firstBook.toString());

對於正確重寫的toString()方法,它會列印一些有用的東西,如下所示:

ISBN: 0201914670; The Swing Tutorial; A Guide to Constructing GUIs, 2nd Edition

上一篇:使用super關鍵字

下一篇:抽象方法和類

相關文章