【源碼解析】Java萬象之源-Object

提到Java,那就不得不說Object類。在面試中,你也可能經常遇到Object類的問題,在這裏總結一番,僅供大家參考。

Object類是Java中所有類的根類,即所有的類都繼承了Object類。其包含的方法如下:

protected Object clone() throws CloneNotSupportedException

創建並返回對象的複製類。通常對於任何對象x,
- x.clone() != x返回爲true
- x.clone().getClass() == x.getClass()返回爲true
- x.clone().equals(x)返回爲true

對象需要被clone,則需要實現Cloneable接口。Cloneable接口只是個標記,沒有任何方法。

更深入的瞭解,對象克隆複製(包含深拷貝、淺拷貝等)請參考 https://www.cnblogs.com/Qian123/p/5710533.html

public boolean equals(Object obj)

判斷兩個對象是否爲同一個對象。equals方法不能作用於null對象,具有以下特徵:
- 自反性

對於任何非空引用值x,始終存在x.equals(x)true
- 對稱性

對於任何非空引用值xy,存在x.equals(y)true時則y.equals(x)也一定返回true
- 傳遞性

對於任何非空引用值xyz,存在x.equals(y)true,則y.equals(z)也爲true,則x.equals(z)也一定返回true
- 一致性

對於任何非空引用值xy,不管多次調用x.equals(y),則始終返回truefalse
- 對於任何非空引用值x,始終存在x.equals(null)false

重寫equals()方法時,應同時重寫hashCode()方法

面試中經常會問到“請談談Object中的==equals()方法的區別”:
其實,在Object類中這兩者沒有什麼差別,均表示兩對象所指向的內存地址是否相同。但是由於Java中存在着多態特性,子類可以重寫equals()方法。譬如,String類中equals()表示兩個字符串的值是否相同。

protected void finalize()

當GC(垃圾回收器)確定對象沒有任何引用的時候,調用此方法。子類可以重寫此方法來釋放系統資源或進行其他的清理。

JVM虛擬機不能確定哪個線程來調用對象的finalize()方法,但是能確定的是調用finalize()方法的線程不會阻塞用戶線程。如果執行方法時拋出異常,則對應對象的finalize()方法終止執行。另外,每個對象都只會執行一次finalize()方法。

public final Class<?> getClass()

返回此對象運行時的類。返回的類對象是由static鎖方法鎖住的對象。

int hashCode()

爲對象返回哈希值。約定如下:
- 在程序相同執行過程中多次調用同個對象,哈希值必須返回相同。但不是相同調用過程則不必相同;
- 如果兩個對象調用equals()方法相同,則hashCode()方法返回值必須相同;
- 如果兩個對象調用equals()方法不相同,並不需要兩個對象的哈希值不相同。但是編程的時候必須意識到,不同的對象產生不同的哈希值可以提高像HashTable這樣類的性能。

void notify()

喚醒等待對象鎖的某單個線程。如果有多個線程在等待,則隨機喚醒其中一個,與其他要佔用對象鎖的線程之間競爭鎖。

void notifyAll()

喚醒等待對象鎖的所有線程。喚醒的線程與其他要佔用對象鎖的線程之間競爭鎖。

String toString()

返回對象的String表示,默認是getClass().getName() + '@' + Integer.toHexString(hashCode())JDK規範要求:一般爲了能清晰打印出對象屬性,建議重寫此方法。

筆者在通常項目中,都會寫個Base類,重寫toString方法,返回JSON字符串。讓所有的自定義類都繼承此Base類。

void wait()

佔用對象鎖的當前線程來調用,釋放擁有的對象鎖,直到其他線程調用notify()或者notifyAll()方法喚醒。

線程調用wait()方法時,可能存在假喚醒,所以此方法必須在循環中使用:

synchronized (obj) {
    while (<condition does not hold>)
        obj.wait();
    // Perform action appropriate to condition
}

void wait(long timeout)

佔用對象鎖的當前線程來調用,釋放擁有的對象鎖,直到其他線程調用notify()或者notifyAll()方法喚醒或者指定時間過後自動喚醒。

void wait(long timeout, int nanos)

佔用對象鎖的當前線程來調用,釋放擁有的對象鎖,直到其他線程調用notify()或者notifyAll()方法喚醒或者指定時間(1000000*timeout + nanos)過後自動喚醒。

擴展閱讀

  1. 【Effective Java】避免使用finalize方法
  2. 【Effective Java】覆蓋equals時請遵守通用約定
  3. 【Effective Java】重寫equals方法時必須重寫hashCode 方法
  4. 【Effective Java】謹慎覆蓋clone方法
發佈了98 篇原創文章 · 獲贊 180 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章