JAVA源碼學習 Object類

Object類是類層次結構的根,它是 Java其他所有類的超類。

在介紹 Object源碼前,補充 native關鍵字:

native關鍵詞修飾的方法是一個原生態方法(本地方法),方法對應的實現不是在當前文件,具體是用C(C++)在DLL中實現的,然後通過JNI調用

以下的源碼是 jdk1.8 版本:

public class Object {

     // 本地方法,作用爲註冊一些本地方法
    private static native void registerNatives();
    
     // 對象初始化時自動調用此方法
    static {
        registerNatives();
    }
    
     // 本地方法,返回當前的運行時類
    public final native Class<?> getClass();
    
     /**
     * 本地方法,計算哈希值,相關的三個規定:
     * 1. 在應用程序執行期間,對於同一對象,不進行修改的前提下,兩次調用該方法得到的哈希值必須相同
     * 2. 對於執行 equals()方法返回爲 true的兩個對象,執行 hashCode()方法,需返回相同的結果
     * 3. 如果根據 equals()方法,兩個對象不相等,執行 hashCode()方法,返回結果不必一定不同,但不同可以提升哈希的性能
     * @return 該對象的哈希值
     */
    public native int hashCode();
    
     /**
     * 用於判斷兩個對象的內容是否相等,具有以下特點:
     * 1. reflexive(自反性),x.equals(x)的結果一定爲 true
     * 2. symmetric(對稱性),x.equals(y)爲 true,當且僅當 y.equals(x)爲 true
     * 3. transitive(傳遞性),當 x.equals(y),y.equals(z),可以推出:x.equals(z)
     * 4. consistent(一致性),對於 x.equals(y),在不修改 x,y的前提下,調用幾次的結果是不變的
     * 5. 當參數爲 null,返回 false
     * 同時要注意,當這個方法被重寫時, hashCode()也應該同步被重寫
     * @return true代表對象與傳入參數相等
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }

     /**
     * 創建並返回該對象的副本,一般要求(非必要):
     * 1. x.clone() != x返回 true
     * 2. x.clone().getClass() == x.getClass()返回 true
     * 3. x.clone().equals(x) true
     * 
     * 注意,Object自身並沒有實現 Cloneable接口,因此不能對其調用 clone方法
     * @return 一個複製的實例
     */
    protected native Object clone() throws CloneNotSupportedException;

     // 返回該對象的字符串表示
     // 獲取字節碼文件的對應全路徑名例如java.lang.Object,並將哈希值轉成16進制數格式的字符串輸出
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    
     // 本地方法,喚醒在此對象監視器上等待的單個線程
    public final native void notify();

     // 本地方法,喚醒在此對象監視器上等待的所有線程
    public final native void notifyAll();
    
     /**
     * 本地方法,使當前線程等待,直到被 notify()或 notifyAll()方法喚醒,或者過去了指定的時間
     * @param 等待的最大毫秒數
     */
    public final native void wait(long timeout) throws InterruptedException;

     * 本地方法,使當前線程等待,直到被 notify()notifyAll()方法喚醒,或者過去了指定的時間
     * @param  timeout 等待的最大毫秒數
     * @param  nanos   額外的時間,以納秒爲範圍 0-999999     
     */
    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");
        }

        // 當傳入的納秒數合法時,將毫秒數 +1
        if (nanos > 0) {
            timeout++;
        }

        // 調用 wait()函數,等待時間爲原傳入最大等待毫秒數 +1
        wait(timeout);
    }

     // 本地方法,使當前線程等待,直到被 notify()或 notifyAll()方法喚醒
    public final void wait() throws InterruptedException {
        wait(0);
    }

     // 本地方法,當垃圾回收期確定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法
    protected void finalize() throws Throwable { }
}


對於上面的源代碼,有一個地方我個人比較不解:
    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 > 0) {
            timeout++;
        }

        wait(timeout);
    }

關鍵在與納秒數,而 1000,000 ns = 1 ms,相當於我們傳入的納秒數,範圍從 [1ns, 1ms),但對於上面的代碼,傳入 100ns,跟 500ns,並沒有什麼不同,所以說明源碼並不支持納秒級別的休眠時間。

而對比 jdk1.6的源代碼:

    public final void wait(long timeout, int nanos) throws nterruptedException {
        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);
    }

當超過半毫秒,或者當毫秒數爲 0,納秒數不爲 0時,加 1。對於這種,800ns跟 900ns也沒有不同,個人推薦納秒級別過於低,因此對納秒進行粗略的處理,但不太能理解從 jdk1.6到 jdk1.8對這個函數的改動有什麼意義。歡迎有其他想法的博友在下方留言交流。

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