JDK1.8源碼閱讀筆記(1)Object類
Object 類屬於 java.lang 包,此包下的所有類在使⽤時⽆需⼿動導⼊,系統會在程序編譯期間⾃動 導⼊。Object 類是所有類的基類,當⼀個類沒有直接繼承某個類時,默認繼承Object類,也就是說任何 類都直接或間接繼承此類,Object 類中能訪問的⽅法在所有類中都可以調⽤。
Object類源碼:
native關鍵字
Java有兩種方法:Java方法和本地方法。Java方法是由Java語言編寫,編譯成字節碼,存儲在class文件中。本地方法是由其他語言(比如C,C++,或者匯編)編寫的,編譯成和處理器相關的機器代碼。本地方法保存在動態連接庫中,格式是各個平台專有的。Java方法是平台無關的,單本地方法卻不是。運行中的Java程序調用本地方法時,虛擬機裝載包含這個本地方法的動態庫,並調用這個方法。本地方法是聯系Java程序和底層主機操作系統的連接方法
被native關鍵字修飾的方法叫做本地方法,簡單地講,一個native方法就是一個java調用非java代碼的接口。一個Native Method是這樣一個java的方法:該方法的實現由非java語言實現,比如C。另外native方法在JVM中運行時數據區也和其它方法不一樣,它有專門的本地方法棧。
Object類源碼
package java.lang;
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" +Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
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);
}
public final void wait() throws InterruptedException {
wait(0);
}
protected void finalize() throws Throwable { }
}
Object類中的12個方法

clone
clone方法可以完成對象的淺克隆。所謂淺克隆就是說被克隆的對象的各個屬性都是基本類型,而不是引用類型(接口、類、數組),如果存在引用類型的屬性,則需要進行深克隆。要想實現 Address的深克隆,首先讓Address類實現 Cloneable 接口,重寫clone方法。
之前的文章中寫過clone方法與深拷貝淺拷貝:Java clone() 方法克隆對象——深拷貝與淺拷貝
protected native Object clone() throws CloneNotSupportedException;
equals
在引用類型中,"=="是比較兩個引用是否指向堆內存里的同一個地址(同一個對象),而equals是一個普通的方法,該方法返回的結果依賴於自身的實現。要比較兩個對象的內容是否相同,需要重寫該方法。
public boolean equals(Object obj) {
return (this == obj);
}
finalize
finalize()是Object的protected方法,子類可以覆蓋該方法以實現資源清理工作,GC在回收對象之前調用該方法,當對象變成(GC Roots)不可達時,GC會判斷該對象是否覆蓋了finalize方法,若未覆蓋,則直接將其回收。否則,若對象未執行過finalize方法,將其放入F-Queue隊列,由一低優先級線程執行該隊列中對象的finalize方法。執行finalize方法完畢后,GC會再次判斷該對象是否可達,若不可達,則進行回收,否則,對象“復活”。
protected void finalize() throws Throwable { }
getClass
Class是一個實實在在的類,在包 java.lang 下,有一個Class.java文件,它跟我們自己定義的類一樣,是一個實實在在的類,Class對象就是這個Class類的實例。在Java里,所有的類的根源都是Object類,而Class也不例外,它是繼承自Object的一個特殊的類,它內部可以記錄類的成員、接口等信息,也就是在Java里,Class是一個用來表示類的類。
public final native Class<?> getClass();
registerNatives
在Object類中,除了有registerNatives這個本地方法之外,還有hashCode()、clone()等本地方法,而在Class類中有forName()這樣的本地方法等等。也就是說,凡是包含registerNatives()本地方法的類,同時也包含了其他本地方法。所以,顯然,當包含registerNatives()方法的類被加載的時候,注冊的方法就是該類所包含的除了registerNatives()方法以外的所有本地方法。使用native方法的好處:
- 通過registerNatives方法在類被加載的時候就主動將本地方法鏈接到調用方,比當方法被使用時再由虛擬機來定位和鏈接更方便有效;
- 如果本地方法在程序運行中更新了,可以通過調用registerNative方法進行更新;
- Java程序需要調用一個本地應用提供的方法時,因為虛擬機只會檢索本地動態庫,因而虛擬機是無法定位到本地方法實現的,這個時候就只能使用registerNatives()方法進行主動鏈接。
registerNatives是⽤ private 關鍵字聲明的,在類外⾯根本調⽤不了。靜態代碼塊就是⼀個類在初始化過程中必定會執⾏的內容,所以在類加載的時候是會執⾏該⽅法的,通過該⽅法來注冊本地⽅法。
private static native void registerNatives();
static {
registerNatives();
}
hashCode
hashCode就是對象的散列碼,是根據對象的某些信息推導出的一個整數值,默認情況下表示是對象的存儲地址。通過散列碼,可以提高檢索的效率,主要用於在散列存儲結構中快速確定對象的存儲地址,如Hashtable、hashMap中。
wait notify notifyAll
這三個方法最終調用的都是jvm級的final native方法
- 如果對象調用了wait方法就會使持有該對象的線程把該對象的控制權交出去,然后處於等待狀態。
- 如果對象調用了notify方法就會通知某個正在等待這個對象的控制權的線程可以繼續運行。
- 如果對象調用了notifyAll方法就會通知所有等待這個對象控制權的線程繼續運行。
其中wait方法有三個over load方法:
- wait()
- wait(long)
- wait(long,int)
wait方法通過參數可以指定等待的時長。如果沒有指定參數,默認一直等待直到被通知。
toString()
getClass().getName()是返回對象的全類名(包含包名),Integer.toHexString(hashCode()) 是以16進制⽆符號整數形式返回此哈希碼的字符串表示形式。打印某個對象時,默認是調⽤ toString ⽅法,⽐如 System.out.println(object),等價於System.out.println(object.toString())。
public String toString() {
return getClass().getName() + "@" +Integer.toHexString(hashCode());
}
