Object 相關概念
Object 是 java 中的頂級父類,它是所有類的超類,所有對象以及數組均會實現這個類提供的方法
JVM 在編譯源碼過程中,遇到沒有繼承 Object 的對象時,編譯器會指定默認父類 Object
接口沒有繼承頂級父類,但會隱式的聲明一套和 Object 中的方法簽名完全一樣的方法,這也就符合萬物皆對象的面向對象思想,任何對象直接或間接的跟 Object 對象有關
Object 類源碼中的關鍵方法
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
···
}
registerNatives():注冊本地方法
它會注冊除 registerNatives
外的所有本地方法。當 java 程序需要調用本地方法時,jvm 會在加載的動態文件里定位并鏈接該本地方法,從而得以執行此方法。
在類被加載時就調用 registerNatives()
的用意是此時是程序主動將本地方法鏈接到調用方,當 java 程序需要調用本地方法時可直接調用,省去了jvm再去定位并鏈接的這一步,這樣做的好處是:
- 更加方便且提高了執行效率
- 當本地方法在程序運行中有更新,調用
registerNatives()
可及時實現更新 - Java程序需要調用一個本地應用提供的方法時,因為虛擬機只會檢索本地動態庫,因而虛擬機是無法定位到本地方法實現的,這個時候就只能使用
registerNatives()
進行主動鏈接 - 通過
registerNatives()
在定義本地方法的實現時,可以不遵守 JNI 的命名規范
···
public final native Class<?> getClass();
getClass():返回此對象的運行時類
返回值是 Class 類型,通過返回的 Class 對象我們可以獲取目標類中包含的所有方法、所有變量、構造函數等
···
public native int hashCode();
hashCode():返回此對象的存儲地址。主要用于判斷對象是否相同,可提高查詢、存儲操作的效率
equals():比較。但它有不同的提供來源
// 這是 Object 類提供的 equals()
···
public boolean equals(Object obj) {
return (this == obj);
}
···
Object 類提供的 equals 方法實際上是比較兩個對象的哈希值
// 這是 String 類提供的 equals()
···
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
···
String 類提供的 equals 方法也會比較哈希值,但并不僅僅之是比較哈希值
如果兩個對象的哈希值相同就說明它們包含的內容一定是相同的,直接返回 true,但如果哈希值不同且傳參進來的對象非 String 類型則直接返回 false
當兩個對象均為 String 類型且長度一致時,則通過 while 循環逐個字符進行比對,并返回最終對比結果
···
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
··
toString():獲取對象的字符串表現形式,組合方式為:類名+@+十六進制哈希碼。當然了,獲取這樣的數據實際意義不大,一般我們都是通過重寫對象 toString() 來傳遞更多具體的數據,如:重寫實體 Bean 的 toString() 觀察數據是否正確或完整
···
protected native Object clone() throws CloneNotSupportedException;
···
clone():創建對象的副本并返回
提供克隆功能的目標對象需實現 Cloneable 接口并重寫 clone(),實現此功能遇到以下場景時會涉及兩個概念,依需而選:
如果此對象被復制的屬性都是基本類型,那么只需要實現當前類的 Cloneable 機制就可以了,這種稱之為淺拷貝。如果被復制對象的屬性中包含其它實體類對象的引用,且這些實體類對象都需要實現cloneable接口并覆蓋clone()方法,這種稱之為深拷貝(其它實體類不實現 Cloneable 機制也可進行拷貝,但就是淺拷貝了,這時指針是指向此實體類原地址的,而非新建地址,因為它并未創建副本)
淺拷貝:被復制對象的所有值屬性都含有與原來對象的相同,而所有的對象引用屬性仍然指向原來的對象
深拷貝:在淺拷貝的基礎上,所有引用其它對象的變量也進行了clone,并指向被復制過的新對象
···
public final native void notify();
···
notify():喚醒正在等待此對象的監視器
線程成為此對象監視器的方法有三種:通過執行此對象的 Synchronized
方法、通過執行屬于此對象的 Synchronized 代碼塊、通過執行該類的靜態 Synchronized
方法,如果該線程不是鎖的持有者,則會拋出 IllegalMonitorStateException
異常
當喚醒發生時,如果有多個線程正在等待此對象,那么其中一個將會被喚醒,但選擇是隨機的(這取決于虛擬機中本功能的具體實現代碼)
···
public final native void notifyAll();
···
notifyAll():喚醒正在等待此對象監視器的所有線程
但此時這些等待線程不會立即執行,它們需要等待調用 notifyAll()
的線程釋放掉鎖后才會執行。同樣的,如果該線程不是鎖的持有者,調用 notifyAll()
會拋出 IllegalMonitorStateException
異常
···
public final native void wait(long timeout) throws InterruptedException;
···
public final void wait() throws InterruptedException {
wait(0);
}
···
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);
}
···
wait() / wait(long timeout) / wait(long timeout, int nanos):使調用該方法的線程釋放共享資源鎖,然后從運行狀態退出,進入等待隊列,直到被再次喚醒 或 定時等待 N 毫秒(如果沒有通知就超時返回)
使用時首先要獲得鎖,需在 synchronized
方法或 synchronized
代碼塊中調用,由 notify()
或 notifyAll()
喚醒
···
protected void finalize() throws Throwable { }
finalize():資源回收
它會在gc啟動,該對象被回收的時候調用
常見問題
final / finally() / finalize() 的區別
final 修飾符,可修飾屬性、方法、類。修飾屬性時表示常量,只可被賦值一次,修飾方法時表示方法鎖定,以防止繼承類對其進行更改,修飾類表示常量類不可被繼承(final類中所有的成員方法也都會隱式的定義為final方法)
finally 異常處理,它只能用在try/catch語句中,并且附帶一個語句塊,表示這段語句最終一定會被執行(不管有沒有拋出異常),經常被用在需要釋放資源的情況下
finalized() 資源回收,它會在gc啟動,該對象被回收的時候調用,用于釋放某些資源
本篇將持續更新 Object 相關知識,一起查漏補缺學個痛快!