JDK源碼學習--Object類

摘要

大家都知道Object是所有類的父類,任何類都默認繼承Object,因此省略了extends Object關鍵字。Objec類中的方法在任何一個java類中都可以使用,下面學習的類的順序以jdk源碼爲準

Object類的常用方法:toString(),getClass(),hashCode(),equals(),clone(),finalize()
定義爲final類型,不能重寫的方法:getClass(),notify(),notifyAll(),wait()


1、registerNatives方法:

private static native void registerNatives();
    static {
        registerNatives();
    }

registerNatives被native修飾爲本地方法,這些方法不是由java語言編寫,通常由C、C++語言編寫。被static修飾爲靜態方法。而且在靜態代碼塊中,Object類加載的時候會先執行registerNatives方法,registerNatives方法會進行一些跟系統有關的方法調用,而這個方法的實現就在java.dll中,裏面會根據不同系統來執行不同的底層操作。


2、getClass方法:

public final native Class<?> getClass();

getClass被native修飾爲本地方法,被final修飾子類不能夠重寫此方法,返回值採用泛型,返回Object的運行時類類型,一般和getName()聯合使用,如getClass().getName()。通過該方法或以獲取類的元數據和方法信息。它能夠獲取一個類的定義信息,然後使用反射去訪問類的全部信息,包括函數和字段。


3、hashCode方法:

    public native int hashCode();

hashCode被native修飾爲本地方法,該方法返回該對象的哈希碼值,hashCode方法在一些具有哈希功能的Collection中用到。用於哈希查找,可以減少在查找中使用equals的次數,重寫了equals方法一般都要重寫hashCode方法。
根據官方文檔的定義,整理以下關鍵點:

  • hashCode的存在主要是用於查找的快捷性,如Hashtable,HashMap等,hashCode是用來在散列存儲結構中確定對象的存儲地址的;
  • 如果兩個對象相同,就是滿足於equals(Java.lang.Object) 方法,那麼這兩個對象的hashCode一定要相同;
  • 如果對象的equals方法被重寫,那麼對象的hashCode也儘量重寫,並且產生hashCode使用的對象,一定要和equals方法中使用的一致,否則就會違反上面第2點;
  • 兩個對象的hashCode相同,並不一定表示兩個對象就相同,也就是不一定適用於equals(java.lang.Object) 方法,只能夠說明這兩個對象在散列存儲結構中,如Hashtable,他們“存放在同一個籃子裏”。
    深入理解hashcode和hash算法請移步於:https://blog.csdn.net/qq_38182963/article/details/78940047

4、equals方法:

public boolean equals(Object obj) {
        return (this == obj);
    }

equals直接判斷this和obj本身的值是否相等,即用來判斷調用equals的對象和形參obj所引用的對象是否是同一對象。這裏的==比較的是對象的引用,也就是"地址值",如果this和obj指向的是同一塊內存對象,則返回true,如果this和obj指向的不是同一塊內存,則返回false。如果希望不同內存但相同內容的兩個對象equals時返回true,則我們需要重寫父類的equal方法,String類已經重寫了object中的equals方法,比較內容是否相等。


5、clone方法:

protected native Object clone() throws CloneNotSupportedException;

clone被native修飾爲本地方法,protected保護方法,實現對象的淺複製,只有實現了Cloneable接口纔可以調用該方法,否則拋出CloneNotSupportedException異常。


6、toString方法:

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

toString方法返回一個字符串,類名+@+哈希值的16進制無符號整數形式。該方法用得比較多,一般子類都有覆蓋。

public class Test1 {  
    public static void main(String[] args){  
        Object o1 = new Object();  
        System.out.println(o1.toString());  
    }  
} 
//輸出:java.lang.Object@7852e922

7、notify方法:

public final native void notify();

notify被native修飾爲本地方法,不可被重寫,該方法喚醒在該對象上等待的某個線程。


8、notifyAll方法:

public final native void notifyAll();

notifyAll被native修飾爲本地方法,不可被重寫,該方法喚醒在該對象上等待的所有線程。


9、wait(long timeout)方法:

public final native void wait(long timeout) throws InterruptedException;

wait被native修飾爲本地方法,不可被重寫,調用該方法後當前線程進入睡眠狀態,讓當前線程等待,使線程等待指定長的時間(毫秒)。在其他線程調用了notify或是notifyAll方法或是達到指定的時長,該線程就可以被調度。其他線程調用了interrupt中斷該線程,就拋出一個InterruptedException異常。


10、wait(long timeout, int nanos)方法:

public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
            timeout++;
        }

        wait(timeout);
    }

wait不可被重寫,和wait(long timeout)方法本質相同,允許更好地控制在放棄之前等待通知的時間,實時量,以毫微秒計算,計算公式如下:1000000*timeout+nanos,特別是wait(0, 0) 表示和wait(0)相同,當前線程必須擁有該對象的監視器。
三種異常:

  • IllegalArgumentException – 如果超時的值是負的或毫微秒的值不在0-999999範圍內。
  • IllegalMonitorStateException – 如果當前線程不是對象監視器的擁有者。
  • InterruptedException – 如果另一個線程中斷了當前線程。當這種異常被拋出當前線程的中斷狀態被清除。

11、wait方法:

public final void wait() throws InterruptedException {
        wait(0);
    }   

實際上調用的是wait(long timeout)方法只不過timeout傳的是0,只有調用了notify或是notifyAll方法,線程纔會被喚醒。


12、finalize方法:

protected void finalize() throws Throwable { }

該方法是protected方法,子類可以覆蓋該方法以實現資源清理工作,GC在回收對象之前調用該方法。該方法與C++中的析構函數不是對應的。C++中的析構函數調用的時機是確定的(對象離開作用域或delete掉),但Java中的finalize的調用具有不確定性。
finalize的執行週期:當對象變成(GC Roots)不可達時,GC會判斷該對象是否覆蓋了finalize方法,若未覆蓋,則直接將其回收。否則,若對象未執行過finalize方法,將其放入F-Queue隊列,由一低優先級線程執行該隊列中對象的finalize方法。執行finalize方法完畢後,GC會再次判斷該對象是否可達,若不可達,則進行回收,否則,對象“復活”。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章