Java基礎學習之--理解Object類
阿新 • • 發佈:2018-12-10
看Java API的Object類, 一共11個方法。按使用的頻度排名:
-
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: 看文件說明
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: 執行Demo
給個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內部的程式碼,比較底層。
其實,這個例子更簡潔的寫法是worker.join()
。 如果看Thread.join()的原始碼,發現它的實現恰好就是呼叫了wait。
-
clone() 這個需要理解深度克隆, 知識點不復雜。
-
getclass() 這個放在後面,但是用得還挺多的,特別是寫框架。
- finalize() 這個已經不他推薦使用了, 儘量不干擾GC的節奏。
總結一下,Object類是Java的基石。這裡比較難一點的就是wait/notify. 學習Java的API, 如果想理解透徹一點,估計繞不開JVM的c++原始碼。