五一回家又斷更了一個放假時間了~~~html
只有光頭才能變強
回顧前面:java
以前花了點之間時間去搞多線程的基礎知識了,難呀難呀難呀....打算還寫一篇線程池的就暫時將多線程系列中止了...面試
今天中午在逛簡書的時候發現一些大廠也會問Object對象裏面有什麼方法(也算是一個知識點吧),Object我還沒去認真複習過,因而這篇主要看看Object對象有什麼要注意的地方~c#
那麼接下來就開始吧,若是文章有錯誤的地方請你們多多包涵,不吝在評論區指正哦~segmentfault
聲明:本文都是使用JDK1.8
咱們學Java的知道,Java是一門面向對象的語言。不管在Java中出現什麼,均可以認爲它是對象(除了八大基本數據類型。固然了,八大基本數據類型也能裝箱成爲對象):微信
extends
繼承)那麼咱們看看Object有什麼方法:多線程
其實就能夠概括成幾個:ide
registerNatives()
【底層實現、不研究】hashCode()
equals(Object obj)
clone()
toString()
notify()
notifyAll()
wait(long timeout)
【還有重載了兩個】finalize()
Object一共有11個方法,其中一個爲底層的實現registerNatives()
,其中兩個wait()
和wait(long timeout, int nanos)
重載方法。post
還有一個屬性:性能
public final native Class<?> getClass();
equals和hashCode方法能夠說是面試的重點題了,配合着String能夠說在面試題中哪都有它們的存在。
首先,咱們來看看equals和hashCode在Object中原生的實現吧:
hashCode:
public native int hashCode();
equals:
public boolean equals(Object obj) { return (this == obj); }
看上去都很是簡單:
hashCode()
由native方法底層實現了。equals()
就直接==
判斷是否相等了。想要更加清晰它們到底是作什麼的,咱們來讀讀它的註釋:
根據註釋咱們能夠總結如下的要點:
equals()
方法,就必須重寫hashCode()
的方法equals()
方法默認是比較對象的地址,使用的是==
等值運算符hashCode()
方法對底層是散列表的對象有提高性能的功能hashCode()
那麼返回的int是相同的!hashCode()
方法默認是由對象的地址轉換而來的equals()
方法還有5個默認的原則:
x.equals(y)
和y.equals(z)
都返回true,那麼能夠得出:x.equals(z)
返回truex.equals(y)
和y.equals(x)
結果應該是相等的。爲啥說hashCode()
以散列表爲底層帶來性能的提高是很容易理解的。咱們再來回顧一下HashMap的插入:
若是hash值都不相等,那麼能夠直接判斷該key是不相等的了!
equals()
方法默認是比較對象的地址,使用的是==
等值運算符。可是按咱們正常開發來講,比較的是對象地址是沒有意義的。
咱們在初學的時候可能就聽過了:String已經實現了equals和hashCode方法了。
下面咱們就來看看它的實現吧:
接下來咱們看看toString方法,也十分簡單:
toString方法主要是用來標識該對象的:
從上面的結果咱們均可以看出來:得出的結果咱們並不能看到什麼東西~
因而咱們通常都重寫toString(),那麼打印出的結果就很方便咱們調試了!
@Override public String toString() { return "Address{" + "provinceNo=" + provinceNo + ", cityNo=" + cityNo + ", streetNo=" + streetNo + '}'; }
下面的結果看起來就好多了:
咱們也來看看它的頂部註釋:
看了上面的註釋咱們能夠總結如下的要點:
下面咱們來看一下淺拷貝:拷貝了Employee對象,可是其成員變量hireday沒有被克隆出去,因此指向的仍是同一個Date對象!
那麼咱們如何克隆對象呢?不管是淺拷貝仍是深拷貝都是這兩步:
淺拷貝:僅僅拷貝了Person對象,而date沒有拷貝!
public class Person implements Cloneable { // 可變的成員變量 private Date date; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
深拷貝:不只拷貝了Person對象,也拷貝了date成員變量
public class Person implements Cloneable { // 可變的成員變量 public Date date; @Override public Object clone() throws CloneNotSupportedException { // 拷貝Person對象 Person person = (Person) super.clone(); // 將可變的成員變量也拷貝 person.date = (Date) date.clone(); // 返回拷貝的對象 return person; } }
不知道有沒有人跟我有相同的疑問:
好比我如今有個Address對象:
public class Address { private int provinceNo; private int cityNo; private int streetNo; public Address() { } public Address(int provinceNo, int cityNo, int streetNo) { this.provinceNo = provinceNo; this.cityNo = cityNo; this.streetNo = streetNo; } }
下面的代碼大家認爲如何?
Address address = new Address(1, 2, 3); address.clone();
咱們都知道:
可能會想:clone()
方法是定義在Object類上的(以protected來修飾),而咱們自定義的Address對象隱式繼承着Object(全部的對象都是Object的子類),那麼子類調用Object以protected來修飾clone()
是徹底沒問題的
出現錯誤的緣由我立馬就想到:是否是我對protected修飾符出現了誤差?
protected修飾的類和屬性,對於本身、本包和其子類可見,這句話自己是沒有錯的。可是還須要補充:對於protected的成員或方法,要分子類和超類是否在同一個包中。與基類不在同一個包中的子類,只能訪問自身從基類繼承而來的受保護成員,而不能訪問基類實例自己的受保護成員。
下面我截兩張圖再來給大家看看(看完圖再看上面的描述,就能理解了):
圖片來源和更多的展開閱讀:https://blog.csdn.net/wangyanguiyiyang/article/details/49800493
wait和notify方法其實就是Java給咱們提供讓線程之間通訊的API。
按照慣例咱們仍是來看註釋怎麼說吧:
wait方法:
notify方法:
notifyAll()方法:
看完上面的註釋咱們能夠總結如下的要點:
不管是wait、notify仍是notifyAll()都須要由監聽器對象(鎖對象)來進行調用
notify()
喚醒的是在等待隊列的某個線程(不肯定會喚醒哪一個),notifyAll()
喚醒的是等待隊列全部線程致使wait()
的線程被喚醒能夠有4種狀況
wait()
時間到了notify()
喚醒notifyAll()
喚醒wait()
的線程會釋放掉鎖 其實總結完上面的並不會有比較深入的印象,能夠嘗試着回答幾個問題來加深對wait()
和notify()
的理解。
從一開始咱們就說了:wait()
和notify()
是Java給咱們提供線程之間通訊的API,既然是線程的東西,那什麼是在Object類上定義,而不是在Thread類上定義呢?
由於咱們的鎖是對象鎖【要是忘記的同窗可回顧:Java鎖機制瞭解一下】,每一個對象均可以成爲鎖。讓當前線程等待某個對象的鎖,固然應該經過這個對象來操做了。
上面已經說了,notify會喚醒某個處於等待隊列的線程。
可是要注意的是:
Thread.sleep()
與Object.wait()
兩者均可以暫停當前線程,釋放CPU控制權。
Object.wait()
在釋放CPU同時,釋放了對象鎖的控制。Thread.sleep()
沒有對鎖釋放參考資料:
finalize()
方法將在垃圾回收器清除對象以前調用,但該方法不知道什麼時候調用,具備不定性
一個對象的finalize()方法 只會被調用一次,並且finalize()被調用不意味着gc會當即回收該對象,因此有可能調用finalize()後,該對象又不須要被回收了,而後到了真正要被回收的時候,由於前面調用過一次,因此不會調用finalize(),產生問題。
參考資料:
進階的資料:
總的來講也算是把Object看了一遍了,不至於一會兒把它的方法給忘了~~~在學習的過程當中也遇到過問題,最明顯的是對protected修飾符又加深了一次理解。
參考資料:
若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠 關注微信公衆號:Java3y。爲了你們方便,剛新建了一下 qq羣:742919422,你們也能夠去交流交流。謝謝支持了!但願能多介紹給其餘有須要的朋友
文章的目錄導航: