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()
返回物件的字串表示形式。
Object
的notify
、notifyAll
和wait
方法都在同步程式中獨立執行的執行緒的活動中發揮作用,這將在後面的課程中討論,這裡不討論,有五個方法:
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()
方法。
對於某些類,Object
的clone()
方法的預設行為可以正常工作,但是,如果一個物件包含對外部物件的引用,比如說ObjExternal
,則可能需要重寫clone()
以獲得正確的行為,否則,一個物件對ObjExternal
所做的更改也將在其克隆中可見,這意味著原始物件及其克隆不是獨立的 — 要將它們分離,你必須重寫clone()
以便它克隆物件和ObjExternal
,然後原始物件引用ObjExternal
,並且克隆引用ObjExternal
的克隆,以便物件及其克隆真正獨立。
equals()方法
equals()
方法將兩個物件進行相等性比較,如果它們相等則返回true
,Object
類中提供的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");
}
即使firstBook
和secondBook
引用了兩個不同的物件,此程式也顯示對objects are equal
,它們被認為是相同的,因為比較的物件包含相同的ISBN號。
如果標識運算子不適合你的類,則應始終重寫equals()
方法。
注意:如果重寫
equals()
,則還必須重寫hashCode()
。
finalize()方法
Object
類提供了一個回撥方法finalize()
,當它變為垃圾時,可以在物件上呼叫它,Object
的finalize()
實現什麼也沒做 — 你可以重寫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()
方法,則更改了兩個物件的等效方式,並且Object
的hashCode()
實現不再有效,因此,如果重寫equals()
方法,則還必須重寫hashCode()
方法。
toString()方法
你應該始終考慮重寫你的類中的toString()
方法。
Object
的toString()
方法返回物件的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