java.lang
包中的Object
類位於類層次結構樹的頂部,每一個類都是Object
類的直接或間接的後代,你使用或編寫的每一個類都繼承Object
的實例方法,你不須要使用任何這些方法,可是,若是你選擇這樣作,你可能須要使用特定於你的類的代碼重寫它們,本節中討論的從Object
繼承的方法是:html
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
方法都在同步程序中獨立運行的線程的活動中發揮做用,這將在後面的課程中討論,這裏不討論,有五個方法:java
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
方法。
若是某個類或其中一個超類實現了Cloneable
接口,則可使用clone()
方法從現有對象建立副本,要建立克隆,請編寫:segmentfault
aCloneableObject.clone();
Object
的此方法實現檢查調用clone()
的對象是否實現Cloneable
接口,若是對象沒有,則該方法拋出CloneNotSupportedException
異常,稍後的課程將介紹異常處理,目前,你須要知道clone()
必須聲明爲:api
protected Object clone() throws CloneNotSupportedException
或oracle
public Object clone() throws CloneNotSupportedException
若是要編寫clone()
方法來覆蓋Object
中的方法。ide
若是調用clone()
的對象確實實現了Cloneable
接口,對象的clone()
方法實現建立與原始對象相同的類的對象,並初始化新對象的成員變量,使其具備與原始對象的相應成員變量相同的值。測試
使類可克隆的最簡單方法是將implements Cloneable
添加到類的聲明中,而後你的對象能夠調用clone()
方法。ui
對於某些類,Object
的clone()
方法的默認行爲能夠正常工做,可是,若是一個對象包含對外部對象的引用,好比說ObjExternal
,則可能須要重寫clone()
以得到正確的行爲,不然,一個對象對ObjExternal
所作的更改也將在其克隆中可見,這意味着原始對象及其克隆不是獨立的 — 要將它們分離,你必須重寫clone()
以便它克隆對象和ObjExternal
,而後原始對象引用ObjExternal
,而且克隆引用ObjExternal
的克隆,以便對象及其克隆真正獨立。線程
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()
。
Object
類提供了一個回調方法finalize()
,當它變爲垃圾時,能夠在對象上調用它,Object
的finalize()
實現什麼也沒作 — 你能夠重寫finalize()
來執行清理,例如釋放資源。
finalize()
方法能夠由系統自動調用,可是何時調用,或者即便調用,也是不肯定的,所以,你不該該依賴此方法爲你進行清理。例如,若是在執行I/O後沒有在代碼中關閉文件描述符,而且你但願finalize()
爲你關閉它們,則可能會耗盡文件描述符。
你不能重寫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()
返回的值是對象的哈希碼,它是十六進制的對象的內存地址。
根據定義,若是兩個對象相等,則它們的哈希碼也必須相等,若是重寫equals()
方法,則更改了兩個對象的等效方式,而且Object
的hashCode()
實現再也不有效,所以,若是重寫equals()
方法,則還必須重寫hashCode()
方法。
你應該始終考慮重寫你的類中的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