Object詳解
Object類是所有類的父類(包括陣列),Object類中共有12個方法(除了init和cinit以外)。
一個靜態本地方法registerNatives,在類被載入時執行。
5個方法可以被子類覆蓋(也在vtable中)—hashCode(),equals(Object obj),clone(),toString(),finalize()。
6個final的方法,基本邏輯都是由本地方法實現,getClass(),notify(),notifyAll(),wait(long timeout),wait(long timeout, int nanos),wait()
registerNatives方法,作用是通過類載入器,載入一些本地方法到jvm中。
Object類在被載入時,會載入下面的methods中的那些本地方法到jvm中。
static JNINativeMethod methods[] = { {“hashCode”, “()I”, (void *)&JVM_IHashCode}, {“wait”, “(J)V”, (void *)&JVM_MonitorWait}, {“notify”, “()V”, (void *)&JVM_MonitorNotify}, {“notifyAll”, “()V”, (void *)&JVM_MonitorNotifyAll}, {“clone”, “()Ljava/lang/Object;”, (void *)&JVM_Clone}, };
public final native Class<?> getClass();
這個方法返回的是類的Class物件,具體值取決於呼叫這個方法的物件。關於Class物件在jvm中的作用,在Java虛擬機器第十篇有描述。
public native int hashCode();
返回一個物件的雜湊值,主要服務於HashMap的hash tables。
hash值需要遵守的約定:
- 一致性(consistent),在程式的一次執行過程中,對同一個物件必須一致地返回同一個整數。
- 如果兩個物件通過equals(Object)比較,結果相等,那麼對這兩個物件分別呼叫hashCode方法應該產生相同的整數結果。
- 如果兩個物件通過java.lang.Object.equals(java.lang.Ojbect)比較,結果不相等,不必保證對這兩個物件分別呼叫hashCode也返回兩個不相同的整數。雖然如此,但是如果2個物件不相等,那麼返回不同的雜湊值有助於雜湊表的儲存。典型實現是把一個物件的地址轉換成整數。
public boolean equals(Object obj)
判斷2個物件是否相等,預設實現是判斷引用是否相等。
一般來說,如果覆蓋了equals方法,那麼需要覆蓋hashcode方法,用於維持相等物件必須有相等的hashcode這一約束。
protected native Object clone() throws CloneNotSupportedException;
建立並返回這個物件的副本,根據約定,這個方法應該呼叫super.clone()。
根據約定,拷貝的物件應該是獨立於當前物件的(也就是說當前物件的修改,不應該影響到拷貝的物件),對於複雜的結構,需要對內部引用的物件也拷貝一次。也就是說預設實現是淺拷貝的,深拷貝需要自己做處理。比如有一個hashMap,則需要先把hashMap複製一個,再把裡面的內容都複製一遍。
如果想呼叫clone方法,需要這個類實現Cloneable介面,否則丟擲java.lang.CloneNotSupportedException異常。
所有的陣列預設實現了 Cloneable介面。
public String toString()
推薦所有的子類都覆蓋這個方法,預設實現返回類名和物件雜湊值的十六進位制。
public final native void notify();
喚醒等待在這個物件的監視器上的一個執行緒,如果很多執行緒在等待,那麼其中一個會被喚醒,具體哪個執行緒被喚醒取決於具體實現。
(一個執行緒呼叫某個物件的wait方法後,會在這個物件的監視器上等待。)
一個物件應該先持有這個物件的監視器(執行物件的同步方法或者同步塊;對於Class物件,執行靜態同步方法),然後才能呼叫這個方法。
如果當前執行緒沒有持有指定物件的鎖,卻呼叫了notify方法,會丟擲IllegalMonitorStateException異常。
public final native void wait(long timeout) throws InterruptedException;
當前執行緒阻塞指定時間,直到時間到了,或者被其它執行緒notify。這個方法會釋放它持有的所有的鎖。
wait(0)的話,就會一直wait,直到被notify。
呼叫這個方法的前提是當前執行緒必須持有這個物件的minotor。
protected void finalize() throws Throwable { }
當這個物件不再被引用時由垃圾回收器呼叫,子類覆蓋這個方法用於釋放系統資源。
在第一次垃圾回收發現不可達時,會先把finalize方法加到F-Q佇列中由專門的執行緒執行,可以在這個方法中自救。如果沒有自救或者自救失敗,這個類就會被標記為可回收的,再下次垃圾回收時如果還是不可達,並且finalize執行過之後,就會真正的回收。
如果finalize方法發生異常,那麼方法會終止,但是異常會被忽略。
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 { }