看Java API的Object類, 一共11個方法。按使用的頻度排名:c++
toString()
這個方法最經常使用在打日誌,定位代碼問題。多線程
equals()
和hashCode()
, 這兩個方法的使用經典例子是HashMap的源碼public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
equals()
比 hashCode()
要經常使用一點。框架
wait()
和 notify()
這個開發不多會直接用到,可是間接用到的場景很多,屬於偏內功的點。wait/notify
屬於Object類最難理解的點了,由於它的基石是多線程。學習思路仍是三步走。step 1: 看文檔說明ide
wait() Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. notify() Wakes up a single thread that is waiting on this object's monitor.
這個文檔說明,看完基本一頭霧水,兩個方法都提到了以下的核心概念thread
, object's monitor
。 先把這些概念放一邊,看看是怎麼用的。學習
step 2: 運行Demothis
給個demo輔助理解,一個線程是幹活的,另外一個線程是管事的。管事的等活幹完驗收。線程
public class WaitNotifyDemo { static class Worker extends Thread{ private volatile int status=0; // 1: 完成, -1: 出錯 @Override public void run(){ try { System.out.println(Thread.currentThread().getName() +": 開始幹活"); Thread.sleep(3000); System.out.println(Thread.currentThread().getName() +": 完成任務"); status = 1; // 通知主線程 synchronized (this){ this.notify(); } } catch (InterruptedException e) { e.printStackTrace(); status = -1; } } public int getStatus(){ return status; } } public static void main(String[] args) throws InterruptedException { Worker worker= new Worker(); worker.start(); synchronized (worker){ int status; while ((status=worker.getStatus())!=1){ worker.wait(); if(status==-1) throw new RuntimeException("出錯了"); } } System.out.println("任務已經完成"); } }
step3: 折騰demo
接下來, 我試了一下, 把notify的代碼去掉,也能正常運行。 這就讓人困惑了,文檔明明說必須調用notify,wait才能結束
。接下來再看文檔:日誌
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup
因此, wait方法必須在while循環中調用。好,解答了一點疑惑。可是每次Worker線程結束時沒有調用notify,主線程就能正常退出, 這個也說不通。 惟一的解釋是: JVM內部在某個地方調用了notify。看openjdk的源碼, 果真如此:從start0開始, 定位到線程在退出時會調用lock.notify_all(thread);
。只是這裏的代碼是JVM內部的代碼,比較底層。 code
其實,這個例子更簡潔的寫法是worker.join()
。 若是看Thread.join()的源碼,發現它的實現剛好就是調用了wait。開發
clone() 這個須要理解深度克隆, 知識點不復雜。
getclass() 這個放在後面,可是用得還挺多的,特別是寫框架。
總結一下,Object類是Java的基石。這裏比較難一點的就是wait/notify. 學習Java的API, 若是想理解透徹一點,估計繞不開JVM的c++源碼。