天天看點

Java源碼解讀:頂級父類Object

類Object是類層次結構的根類。每個類都使用Object作為超類,所有對象都實作這個類的方法。

  1. 方法簽名
private static native void registerNatives();
//傳回此Object運作時類型
public final native Class<?> getClass();
//傳回對象的哈希值
public native int hashCode();
//判斷其他對象是否與此對象"相等"
public boolean equals(Object obj);
//建立并傳回此對象的一個副本
protected native Object clone() throws CloneNotSupportedException;
//傳回此對象的字元串表示
public String toString();
//喚醒在此對象螢幕上等待的單個線程
public final native void notify();
//喚醒在此對象螢幕等待的所有線程
public final native void notifyAll();
//在其他線程調用此對象的notify()方法或notifyAll()方法前,或者超過指定的時間量前,讓目前線程等待
public final void wait() throws InterruptedException;
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException
//當垃圾回收器确定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法
protected void finalize() throws Throwable;    
           
  1. 具體詳解

equals方法

public boolean equals(Object obj) {
        return (this == obj);
    }
           
由源碼可知,預設的Object的equals方法隻是比較對象的位址,對于String這樣的類要通過equals比較内容,必須寫equals方法。

equals方法重寫必須注意以下幾點
   (1)重寫的equals方法的通路權限必須是public的,因為Object中的該方法已經是public的了,重寫的方法的通路權限不能低于父類的
   (2)方法的入參必須是Object類型,不能使用其他類型

 正确的equals方法必須滿足5個條件
   (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(x)傳回true,則x.equals(z)一定傳回true。
   (4)一緻性。對任意x和y,如果對象中用于等價比較的資訊沒有改變,那麼無論調用x.equals(y)多少次,傳回的結果應該保持一緻。
   (5)對任何不适null的x,x.equals(null)一定傳回false。
           

hashCode方法

public native int hashCode();
           
通常的方法時将成員變量與某一素數相乘,目的是使哈希碼既能滿足要求,又能均勻分布。
 (1)Java應用程式期間,于同一對象多次調用hashCode方法時,在對象上參與equals比較的成員沒有被修改的情況下,必須一緻地傳回相同的整數
 (2)從某一個應用程式的一次執行到同一應用的另一次執行,該整數無須保持一緻。
 (3)如果兩個對象各自調用hashCode方法産生的不同結果,對這兩個對象進行equals方法的比較一定要傳回false。
 (4)如果根據equals方法比較。兩個對象時等價的,那麼在兩個對象中各自調用hashCode方法必須産生相同的整數結果
 (5)如果根據equals方法比較,兩個對象不等價,那麼在兩個對象中各自調用hashCode方法不一定會産生不同的整數結果。
           

equals方法和hashCode方法的關系

(1)如果重寫了equals方法,則必須重寫hashCode防止兩個等價的對象的hashCode值不同,這在集合中将造成嚴重後果。
 (2)如果equals成立,則hashCode必須相同,如果hashCode不同,則equals則一定不成立
           

notify方法與notifyAll方法

public final native void notify();
public final native void notifyAll();
           
notify方法喚醒在此對象螢幕上等待的單個線程,如果此螢幕上有多個對象在等待,則會選擇喚醒其中一個線程,選擇是任意的。而notifyAll會喚醒所有線程。線程通過調用其中一個wait方法,在對象螢幕上等待。直到目前線程放棄此對象的鎖定,才能繼續執行被喚醒的線程。被喚醒的線程将以正常方式與該對象上主動同步的其他所有線程進行競争。
           

一次隻能有一個線程擁有對象的螢幕

此方法隻應由作為同步螢幕的所有者的線程來調用。通過以下三種方式之一,線程可以成為此對象螢幕的所有者:
(1)通過執行此對象的同步執行個體的方法
(2)通過執行在此對象上進行同步的synchronized語句的正文.
(3)對于Class類型的對象,可以通過執行該類的同步靜态方法。
如果目前線程不是此對象螢幕的所有者,則調用該方法會抛出IllegalMonitorStateException。
           

wait方法

public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < ) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos <  || nanos > ) {
            throw new IllegalArgumentException(
               "nanosecond timeout value out of range");
        }
        if (nanos >=  || (nanos !=  && timeout == )) {
            timeout++;
        }
        wait(timeout);
    }
           
wait方法導緻目前線程等待,直到其他線程調用該同步螢幕的notify方法或者notifyAll方法。
如果目前線程不是此對象螢幕所有者,将抛出IllegalMonitorStateException異常。
如果在目前線程等待通知之前或者正在等待通知時,任何線程終端了目前線程。都會抛出InterruptedException異常。
           

finalize方法

protected void finalize() throws Throwable { }
           
當JVM已确定尚未終止的任何線程無法再通過任何方法通路此對象時,将調用此方法,除非由于準備終止的其他某個對象或類的終結操作執行了某個操作。
對于任何給定對象,JVM最多隻調用一次 finalize 方法。 
           

toString方法

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
           
傳回該對象的字元串表示,Object 類的 toString 方法傳回一個字元串,該字元串由類名(對象是該類的一個執行個體)、标記符“@”和此對象哈希碼的無符号十六進制表示組成。
           

clone方法

protected native Object clone() throws CloneNotSupportedException;
           
建立并傳回此對象的一個副本。“副本”的準确含義可能依賴于對象的類。Object 類的 clone 方法執行特定的複制操作。
首先,如果此對象的類不能實作接口 Cloneable,則會抛出 CloneNotSupportedException。
Object 類本身不實作接口 Cloneable,是以在類為 Object 的對象上調用clone 方法将會導緻在運作時抛出異常。