文章目錄
Object 的重要性
學習 Java 的同學都知道,Object 是一個很重要的類,它是所有類的父類。在日常開發中我們可能經常要與 Object 打交道,如果還不熟悉 Object ,肯定是說不過去的。
我認爲熟悉 Java 很難,熟悉 Object 卻不難,單單一個 Object 尚且不敢言勝,我們又哪有勇氣去深入剖析 Java 的內核呢?
Object 的源碼
紙上談兵終歸是落了下乘,想要真正熟悉 Object ,我們還得從源碼入手。
package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
public class Object {
@HotSpotIntrinsicCandidate
public Object() {}
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
@HotSpotIntrinsicCandidate
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
@HotSpotIntrinsicCandidate
public final native void notify();
@HotSpotIntrinsicCandidate
public final native void notifyAll();
public final void wait() throws InterruptedException {
wait(0L);
}
public final native void wait(long timeoutMillis) throws InterruptedException;
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
@Deprecated(since="9")
protected void finalize() throws Throwable { }
}
從源碼中我們可見,Object 共有 11 個方法。而且大部分方法前面都帶有 native 修飾符,這個修飾符表示本方法爲本地方法,該方法的實現並不是 Java,而是 C/C++,而且方法的實現並不在本文件中。
爲什麼這部分的方法的實現要使用別的語言,而不能是 Java 呢?一方面,Object 的方法大部分與底層有關,且 Java 不能操作操作系統底層,但是可以通過 JNI 接口調用其他語言來實現對底層的訪問,另外一個角度,使用本地方法可能在性能方面更有優勢一點。
對 Object 各個方法的簡介
getClass 方法
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
該方法是一個本地方法,由 final 修飾可知該方法不允許子類重寫,它返回一個 Class 對象,該對象使用的是哪一個類的構造函數,返回的就是哪一個類的 Class 對象。該方法經常在反射機制中被用到。
hashCode 方法
@HotSpotIntrinsicCandidate
public native int hashCode();
該方法是一個本地方法,返回對象的哈希碼。
equals 方法
public boolean equals(Object obj) {
return (this == obj);
}
一般用於比較兩個對象是否相等,在未被子類重寫的情況下 equals 用於比較兩個對象的內存地址是否相等。
clone 方法
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
該方法是一個本地方法,用於創建並返回當前對象的一份拷貝。
toString 方法
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
該方法返回對象的字符串表示形式,其實實際上返回的是一個 “類名@哈希碼” 的字符串。
notify 方法
@HotSpotIntrinsicCandidate
public final native void notify();
該方法是一個本地方法,由 final 修飾可知該方法不允許子類重寫,作用爲喚醒一個在此對象鎖上等待的線程,如果有多個線程在等待則只會喚醒一個。
notifyAll 方法
@HotSpotIntrinsicCandidate
public final native void notifyAll();
該方法是一個本地方法,由 final 修飾可知該方法不允許子類重寫,作用與 notify 相似,其區別爲 notifyAll 會喚醒在此對象鎖上等待的所有線程,而不僅僅是一個。
wait 方法
public final void wait() throws InterruptedException {
wait(0L);
}
public final native void wait(long timeoutMillis) throws InterruptedException;
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
該方法是一個本地方法,由 final 修飾可知該方法不允許子類重寫,一般與 notify/notifyAll 配套使用,作用爲讓當前正在執行的線程進入線程阻塞狀態的等待狀態,它只能在同步代碼塊或同步方法中調用,且執行後當前線程釋放鎖。
finalize 方法
@Deprecated(since="9")
protected void finalize() throws Throwable { }
finalize 方法與 Java 的垃圾回收機制有關,在垃圾回收器準備釋放對象佔用的存儲空間時,會首先調用其 finalize 方法(每個對象的 finalize 方法只能被執行一次),如果它能夠與引用鏈(GC-Roots)上的任何一個對象關聯,就可以存活下來,否則將會被回收。