Java 是一門面向對象的語言,在 Java 裏面一切均可以看做是一個對象,而 Java 裏面全部的對象都默認繼承於 Object 類,因此狗哥今天就複習了一遍這個類。java
上圖看出 Object 一共有 12 個方法,其中 registerNatives() 是由 C 語言實現的,這個不在研究範圍內。ide
/** * Returns the runtime class of this {@code Object}. The returned * {@code Class} object is the object that is locked by {@code * static synchronized} methods of the represented class. */ public final native Class<?> getClass();
這個方法的做用就是返回某個對象的運行時類,它的返回值是 Class 類型,Class c = obj.getClass();經過對象 c ,咱們能夠獲取該對象的全部成員方法,每一個成員方法都是一個 Method 對象;咱們也能夠獲取該對象的全部成員變量,每一個成員變量都是一個 Field 對象;一樣的,咱們也能夠獲取該對象的構造函數,構造函數則是一個 Constructor 對象。這個方法在反射時會經常使用到。函數
/** * Returns a hash code value for the object. This method is * supported for the benefit of hash tables such as those provided by * {@link java.util.HashMap}. */ public native int hashCode();
這個方法的註釋比較長,就不放出來了。註釋指出:this
public boolean equals(Object obj) { return (this == obj); }
equals 的實現很是簡單,它的做用就是比較兩個對象是否相等,而比較的依據就是兩者的內存地址。除此以外,equals 還遵循如下幾個原則:spa
一、自反性:x.equals(x); // true 二、對稱性:x.equals(y) == y.equals(x); // true 三、傳遞性:if (x.equals(y) && y.equals(z)) x.equals(z); // true; 四、一致性,只要對象沒有被修改,屢次調用 equals() 方法結果不變: x.equals(y) == x.equals(y); // true 五、非空性,對任何不是 null 的對象 x 調用 x.equals(null) 結果都爲 false : x.equals(null); // false;
爲何要重寫 hashcode 和 equals ?.net
這個問題以前分享過舊文:https://mp.weixin.qq.com/s/iI...線程
protected native Object clone() throws CloneNotSupportedException;
clone() 是 Object 的 protected 方法,它不是 public,一個類不顯式去重寫 clone(),其它類就不能直接去調用該類實例的 clone() 方法。此外,Clone 的註釋中還提到比較重要的幾點:3d
關於淺拷貝與深拷貝的詳解,請看這篇舊文:
https://mp.weixin.qq.com/s/I6...代理
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
這個方法應該沒什麼好講的,原生的 toString 方法僅僅返回,對象名 + 它的 hashCode ,但作過開發的都知道,原生的 toString 做用不大。咱們須要重寫 toString 通常是由於方便調試,須要知道對象的屬性值,而不只僅是 hashCode 。因此,應該像下面這樣重寫:調試
public class Student { private int age; private String name; // 省略 get、set @Override public String toString() { return "Student{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
public final native void notify(); public final native void notifyAll();
首先是 notify ,註釋就不貼出來了,notify 的做用就是隨機喚醒在等待隊列的某個線程,而 notifyAll 就是喚醒在等待隊列的全部線程。
public final void wait() throws InterruptedException { wait(0); } public final native void wait(long timeout) throws InterruptedException; 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 的做用是讓當前線程進入等待狀態,同時,wait() 也會讓當前線程釋放它所持有的鎖。直到其餘線程調用此對象的 notify() 方法或 notifyAll() 方法,當前線程被喚醒進入就緒狀態。
wait(long timeout) (以毫秒爲單位)讓當前線程處於等待(阻塞)狀態,直到其餘線程調用此對象的notify() 方法或 notifyAll() 方法,或者超過指定的時間量,當前線程被喚醒進入就緒狀態。
wait(long timeout, int nanos) 和 wait(long timeout) 功能同樣,惟一的區別是這個能夠提供更高的精度。總超時時間(以納秒爲單位)計算爲 1000000 *timeout+ nanos。By the way ,wait(0,0) 和 wait(0) 效果同樣。
除此以外,notify 和 wait 的註釋中還有這麼一段:
* <p> * This method should only be called by a thread that is the owner * of this object's monitor. A thread becomes the owner of the * object's monitor in one of three ways: * <ul> * <li>By executing a synchronized instance method of that object. * <li>By executing the body of a {@code synchronized} statement * that synchronizes on the object. * <li>For objects of type {@code Class,} by executing a * synchronized static method of that class. * </ul> * <p>
看到這英文,剛過四級的我瑟瑟發抖。以上註釋主要就是描述了,notify 和 wait 方法的使用規範。意思就是這兩者必須在 synchronized 修飾的同步方法或同步代碼中使用。
答:調用 wait() 就是釋放鎖,釋放鎖的前提是必需要先得到鎖,先得到鎖才能釋放鎖。
答:notify()、notifyAll() 是將鎖交給含有 wait() 方法的線程,讓其繼續執行下去,若是自身沒有鎖,怎麼叫把鎖交給其餘線程呢?(本質是讓處於入口隊列的線程競爭鎖)
詳細解釋請參考這篇博文:https://blog.csdn.net/qq_42145871/article/details/81950949
首先,兩者均可以暫停當前線程,釋放 CPU 控制權。主要的區別在於 Object.wait()在釋放 CPU 同時,釋放了對象鎖的控制。而 Thread.sleep() 沒有對鎖釋放。換句話說 sleep 就是耍流氓,佔着茅坑不拉屎。