#################
object類
#################
JDK中所有類的基類--java.lang.Object
Object類的結構圖

什么是native方法?
native關鍵字標識的Java方法為本地方法,底層是由C/C++程序編譯后dll文件,Java加載dll文件后,可通過本地方法調用dll函數。
1.類構造器
是創建Java對象的途徑之一,通過new關鍵字調用構造器完成對象的實例化,或通過構造器對象進行相應的初始化。在JDK的object類源碼中,系統會自動添加一個無參構造器。
1 public Object(){} 2 Object obj =new Object(); //構造一個Object類的對象
2.registerNatives方法
1 private static native void registerNatives(); 2 static { 3 registerNatives(); 4 }
靜態代碼塊是一個類在初始化過程中必定會執行的內容,所以在類加載時會執行該方法,通過該方法來注冊本地方法。
3.getClass方法
public final native Class<?> getClass();
首先,該方法由final聲明本地方法,不能被重寫,作用是返回運行時類對象,通過這個類對象可以獲取該運行時類的相關屬性和方法。
class是一個類的屬性,能獲取該類編譯時的類對象;而getClass()是一個類的方法,它是獲取該類運行時的類對象。
4.hashcode方法
1 public native int hashCode()
這是一個由native聲明的本地方法,作用是返回對象的哈希碼(是int類型的數值)。
哈希算法也稱為散列算法,是將數據依據特定算法產生的結果直接指定到一個地址上,這個結果就是由hashcode方法產生的。當集合要添加新元素時,會先調用這個元素的hashcode方法,就能定位到它應該放置的物理位置上。
1)如果這個位置上沒有元素,就直接存儲在這個位置上,不用再進行任何比較;
2)如果這個位置上已經有元素,就調用它的equals方法與新元素進行比較,相同的話就不存了;不同的話(也就是產生了hash沖突),那么就在這個key的位置產生一個鏈表,將所有hashcode相同的對象存放在這個單鏈表上。
如果兩個對象的equals值比較相等,那么它們的hashcode值一定相等;如果兩個對象的equals值比較不相等,那么他們的hashcode值可能相等,也可能不相等。
5.equals方法
1 public boolean equals(Object obj) { 2 return (this == obj); 3 }
5.1 Object中的equals方法比較的是對象的地址是否相同;equals方法可以被重寫,重寫后equals方法比較的是兩個對象值是否相同。
5.2 在Java規范中,對equals方法的使用必須遵循以下幾個規則:
自反性:對於任何非空引用值X,X.equals(X)都應返回true;
對稱性:對於任何非空引用值X和Y,當且僅當Y.equals(X)返回true時,X.equals(Y)也應該返回true;
傳遞性:對於任何非空引用值X,Y,Z,如果X.equals(Y)返回true,並且Y.equals(Z)返回true,那么X.equals(Z)應返回true;
一致性:對於任何非空引用值X和Y,多次調用X.equals(Y)始終返回true或始終返回false。
5.3 equals和==的區別?
equals比較的是兩個對象值是否相等,如果沒有被重寫,比較的是對象的引用地址是否相同;
==用於比較基本數據類型的值是否相等,或比較兩個對象的引用地址是否相等;
1 String hello = new String("hello"); 2 String hello1 = new String("hello"); 3 System.out.println(hello.equals(hello1)); //重寫了,比較的是值,輸出結果為true
4 System.out.println(hello == hello1); //比較的是引用地址,輸出結果為false 5 //比較基本類型的值
6 int age = 10; 7 int age2 = 10; 8 System.out.println(age == age2); //輸出為true
6.clone方法
1 protected native Object clone() throws CloneNotSupportedException;
clone方法是創建並返回一個對象復制后的結果。
如果一個類沒有實現Cloneable接口(只是一個標記接口),那么對此類對象進行賦值時,會出現CloneNotSupportedException異常。
clone生成的新對象與原對象的關系,區別在於兩個對象間是否存在相同的引用或對應的內存地址是否存在共用情況;若存在,則為“淺復制”,否則為“深復制”,“深復制”時需要將共同關聯的引用也復制完全。
7.toString方法
1 public String toString() { 2 return getClass().getName() + "@" + Integer.toHexString(hashCode()); 3 }
打印某個對象時,默認是調用toString()方法。
比如System.out.print(person)等價於System.out.print(person.toString()); //默認返回對象的地址
getClass().getName是返回對象的全類名,Integer.toHexString(hashCode())是以16進制無符號整數形式返回此哈希碼的字符串表示形式。
8.notify方法
1 public final native void notify();
喚醒可能等待該對象的對象鎖的其他線程。由JVM(與優先級無關)隨機挑選一個處於wait狀態的線程。
在調用notify()之前,線程必須獲取該對象的對象鎖,執行完notify()方法后,不會馬上釋放鎖,直到退出synchronized代碼塊,當前線程才會釋放鎖;notify一次只能隨機通知一個線程進行喚醒。
9.notifyAll方法
1 public final native void notifyAll();
使所有正在等待池中等待同一個共享資源的全部線程從等待狀態退出,進入可運行狀態,讓它們同時競爭對象鎖,只有獲得鎖的線程才能進入就緒狀態。
10.wait(long timeout)方法
1 public final native void wait(long timeout) throws InterruptedException;
11.wait(long timeout,int nanos)方法
1 public final void wait(long timeout, int nanos) throws InterruptedException { 2 if (timeout < 0) { 3 throw new IllegalArgumentException("timeout value is negative"); 4 } 5
6 if (nanos < 0 || nanos > 999999) { 7 throw new IllegalArgumentException( 8 "nanosecond timeout value out of range"); 9 } 10
11 if (nanos > 0) { 12 timeout++; 13 } 14
15 wait(timeout); 16 }
wait(long timeout , int nanos)方法的實現只要nanos大於0,那么timeout時間就加上一毫秒,主要是更精確地控制時間,其他的跟wait(long timeout)一樣。
12.wait方法
1 public final void wait() throws InterruptedException { 2 wait(0); 3 }
wait方法會引起當前線程阻塞,直到另外一個線程在對應的對象上調用notify或notifyAll方法,或達到了方法參數中指定的時間。
調用wait方法的當前線程一定要擁有對象的監視器鎖。
wait方法會把當前線程放在對應的等待隊列中,在這個對象上的所有同步請求都不會得到響應。線程調用將不會調用線程,線程一直處於休眠狀態。要注意的是,wait方法把當前線程放置到這個對象的等待隊列中,解鎖也僅僅是在這個對象上;當前線程在等待過程中仍然持有其他對象的鎖。
如果當前線程被其他線程在當前線程等待之前或正在等待時調用了interrupt()中斷了,那么就會拋出InterruptException異常。
13.1 為什么wait方法一般要寫在while循環里?
答:在某個線程調用notify到等待線程被喚醒的過程中,有可能出現另一個線程得到了鎖並修改了條件使得條件不再滿足;只有某些等待線程的條件滿足了,但通知線程調用了notifyAll有可能出現“偽喚醒”。
13.2 wait方法和sleep方法的區別?
答:wait方法屬於object類,當調用wait方法時,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify方法后本線程才會進入對象鎖定池,准備獲取對象鎖進入運行狀態。sleep方法屬於thread類,sleep方法導致程序暫停執行指定的時間,讓出CPU給其他線程,但是它的監控狀態依然保持,當指定的時間到了又會恢復運行狀態。在調用sleep方法過程中,線程不會釋放對象鎖。
13.finalize方法
1 protected void finalize() throws Throwable { }
該方法用於垃圾回收,一般由JVM自動調用,不需要程序員手動調用該方法。
