如圖可知,Object類有12個成員方法,按照用途可以分為以下幾種
1,構造函數
2,hashCode和equals函數用來判斷對象是否相同,
3,wait(),wait(long),wait(long,int),notify(),notifyAll()
4,toString()和getClass,
5,clone()
6,finalize()用於在垃圾回收
函數說明
clone()
clone()函數的用途是用來另存一個當前存在的對象。(克隆)
hashCode()和equals()
- equals()用於確認兩個對象是否相同。
- hashCode()用於獲取對象的哈希值。
- 哈希值相同的對象不一定equals(),equals()返回true的兩個對象一定相同。
Java中Object類的equals()和hashCode()方法深入解析
1.equals()
在初學Java的時候,很多人會說在比較對象的時候,==是比較地址,equals()是比較對象的內容,誰說的?
看看equals()方法在Object類中的定義:
public boolean equals(Object obj){
return (this == obj);
}
但是為什么會有equals是比較內容的這種說法呢?
因為在String、Double等封裝類中,已經重寫(overriding)了Object類的equals()方法,於是有了另一種計算公式,是進行內容的比較。
比如在String類中:
public int hashCode() {
int h = hash;
if (h == 0) {
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
2.hashCode()
在Object類中的定義為:
public native int hashCode();
是一個本地方法,返回的對象的地址值。
但是,同樣的思路,在String等封裝類中對此方法進行了重寫。方法調用得到一個計算公式得到的int值。
3.兩者的關系
①兩個obj,如果equals()相等,hashCode()一定相等
②兩個obj,如果hashCode()相等,equals()不一定相等
原因:從散列的角度考慮,不同的對象計算哈希碼的時候,可能引起沖突,大家一定還記得數據結構中沖突的解決方案吧。
但是為什么要這樣設計這兩個函數,個人的理解是為了比較兩個對象時更高效。
可以考慮在Java集合中,判斷兩個對象是否相等的規則是:
第一步,如果hashCode()相等,則查看第二步,否則不相等;
第二步,查看equals()是否相等,如果相等,則兩obj相等,否則還是不相等。
為什么這樣做?個人的理解是讓適當的函數完成適當的功能,畢竟hashCode()比equals()在某種程度上來得快。
toString()和getClass()
toString()返回一個String對象,將信息變為字符串返回,默認輸出對象地址,若輸出對象的地址,我們並不能看懂它的意思,那么就要通過重寫Object類的toString方法來輸出對象屬性信息。
getClass()返回此Object的運行時類,返回的類對象是被表示類的static synchronized方法鎖定的對象。
返回一個Class對象如果打印出來會發現結果是如下格式
class package.name.xxx
因為返回的是一個class對象,后面可以跟class類的方法。用的是誰的構造函數,那么getClass返回的就是誰的類型。
getClass()經常用於java反射機制
wait(),wait(long),wait(long,int),notify(),notifyAll()
² 這幾個函數體現的是Java的多線程機制
² 在使用的時候要求在synchronize語句中使用
² wait()用於讓當前線程失去操作權限,當前線程進入等待序列
² notify()用於隨機通知一個持有對象的鎖的線程獲取操作權限
² notifyAll()用於通知所有持有對象的鎖的線程獲取操作權限
² wait(long) 和wait(long,int)用於設定下一次獲取鎖的距離當前釋放鎖的時間間隔
notify和notifyAll的區別 - 何時使用
參考地址:https://blog.csdn.net/u014658905/article/details/81035870
Java中notify和notifyAll的區別
Java提供了兩個方法notify和notifyAll來喚醒在某些條件下等待的線程,你可以使用它們中的任何一個,但是Java中的notify和notifyAll之間存在細微差別,這使得它成為Java中流行的多線程面試問題之一。
當你調用notify時,只有一個等待線程會被喚醒而且它不能保證哪個線程會被喚醒,這取決於線程調度器。雖然如果你調用notifyAll方法,那么等待該鎖的所有線程都會被喚醒,但是在執行剩余的代碼之前,所有被喚醒的線程都將爭奪鎖定,這就是為什么在循環上調用wait,因為如果多個線程被喚醒,那么線程是將獲得鎖定將首先執行,它可能會重置等待條件,這將迫使后續線程等待。
因此,notify和notifyAll之間的關鍵區別在於notify()只會喚醒一個線程,而notifyAll方法將喚醒所有線程。
何時在Java中使用notify和notifyAll
如果所有線程都在等待相同的條件,並且一次只有一個線程可以從條件變為true,則可以使用notify or notifyAll。
在這種情況下,notify是優於notifyAll因為喚醒所有這些因為我們知道只有一個線程會受益而所有其他線程將再次等待,所以調用notifyAll方法只是浪費CPU。
雖然這看起來很合理,但仍有一個警告,即無意中的接收者吞下了關鍵通知。通過使用notifyAll,我們確保所有收件人都會收到通知
總結:
1)如果我使用notify(),將通知哪個線程?
無法保證,ThreadScheduler將從等待該監視器上的線程的池中選擇一個隨機線程。保證只有一個線程會被通知(隨機性)
2) 我怎么知道有多少線程在等待,所以我可以使用notifyAll()?
它取決於程序邏輯,在編碼時需要考慮一段代碼是否可以由多個線程運行。理解線程間通信的一個很好的例子是在Java中實現生產者 - 消費者模式。
3) 如何調用notify()?
Wait()和notify()方法只能從synchronized方法或塊中調用,需要在其他線程正在等待的對象上調用notify方法。
4) 什么是這些線程等待被通知等?
線程等待某些條件,例如在生產者 - 消費者問題中,如果共享隊列已滿,則生產者線程等待,如果共享隊列為空,則生成者線程等待。由於多個線程正在使用共享資源,因此它們使用wait和notify方法相互通信。
finalize()
當垃圾收集確定不再有對該對象的引用時,垃圾收集器在對象上調用該對象。
這個函數在進行垃圾回收的時候會用到,匿名對象回收之前會調用到,具體的例子如圖所示