亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Object對(duì)象你真理解了嗎?

anquan / 3317人閱讀

摘要:無(wú)論在中出現(xiàn)什么,都可以認(rèn)為它是對(duì)象除了八大基本數(shù)據(jù)類型。讓當(dāng)前線程等待某個(gè)對(duì)象的鎖,當(dāng)然應(yīng)該通過(guò)這個(gè)對(duì)象來(lái)操作了。但是要注意的是方法調(diào)用后,被喚醒的線程不會(huì)立馬獲得到鎖對(duì)象。主要的區(qū)別在于在釋放同時(shí),釋放了對(duì)象鎖的控制。

前言

五一回家又?jǐn)喔艘粋€(gè)放假時(shí)間了~~~

只有光頭才能變強(qiáng)

回顧前面:

ThreadLocal就是這么簡(jiǎn)單

多線程三分鐘就可以入個(gè)門了!

多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍

Java鎖機(jī)制了解一下

AQS簡(jiǎn)簡(jiǎn)單單過(guò)一遍

Lock鎖子類了解一下

之前花了點(diǎn)之間時(shí)間去搞多線程的基礎(chǔ)知識(shí)了,難呀難呀難呀....打算寫(xiě)一篇線程池的就暫時(shí)將多線程系列停止了...

今天中午在逛簡(jiǎn)書(shū)的時(shí)候發(fā)現(xiàn)一些大廠也會(huì)問(wèn)Object對(duì)象里面有什么方法(也算是一個(gè)知識(shí)點(diǎn)吧),Object我還沒(méi)去認(rèn)真復(fù)習(xí)過(guò),于是這篇主要看看Object對(duì)象有什么要注意的地方~

那么接下來(lái)就開(kāi)始吧,如果文章有錯(cuò)誤的地方請(qǐng)大家多多包涵,不吝在評(píng)論區(qū)指正哦~

一、Object對(duì)象簡(jiǎn)介
聲明:本文都是使用JDK1.8

我們學(xué)Java的知道,Java是一門面向?qū)ο蟮恼Z(yǔ)言。無(wú)論在Java中出現(xiàn)什么,都可以認(rèn)為它是對(duì)象(除了八大基本數(shù)據(jù)類型。當(dāng)然了,八大基本數(shù)據(jù)類型也能裝箱成為對(duì)象):

而Object就是這些對(duì)象的最高級(jí)別的,所有的Java對(duì)象都隱式地繼承了Object對(duì)象(不用顯示寫(xiě)extends繼承)

所有的Java對(duì)象都擁有Object默認(rèn)的方法。

那么我們看看Object有什么方法:

其實(shí)就可以歸納成幾個(gè):

registerNatives()【底層實(shí)現(xiàn)、不研究】

hashCode()

equals(Object obj)

clone()

toString()

notify()

notifyAll()

wait(long timeout)【還有重載了兩個(gè)】

finalize()

Object一共有11個(gè)方法,其中一個(gè)為底層的實(shí)現(xiàn)registerNatives(),其中兩個(gè)wait()wait(long timeout, int nanos)重載方法。

所以我們真正需要看的就是8個(gè)方法

還有一個(gè)屬性

 public final native Class getClass();

二、equals和hashCode方法

equals和hashCode方法可以說(shuō)是面試的重點(diǎn)題了,配合著String可以說(shuō)在面試題中哪都有它們的存在。

首先,我們來(lái)看看equals和hashCode在Object中原生的實(shí)現(xiàn)吧:

hashCode:

public native int hashCode();

equals:

    public boolean equals(Object obj) {
        return (this == obj);
    }

看上去都非常簡(jiǎn)單:

hashCode()由native方法底層實(shí)現(xiàn)了。

equals()就直接==判斷是否相等了。

想要更加清晰它們究竟是做什么的,我們來(lái)讀讀它的注釋:

根據(jù)注釋我們可以總結(jié)以下的要點(diǎn)

重寫(xiě)equals()方法,就必須重寫(xiě)hashCode()的方法

equals()方法默認(rèn)是比較對(duì)象的地址,使用的是==等值運(yùn)算符

hashCode()方法對(duì)底層是散列表的對(duì)象有提升性能的功能

同一個(gè)對(duì)象(如果該對(duì)象沒(méi)有被修改):那么重復(fù)調(diào)用hashCode()那么返回的int是相同的!

hashCode()方法默認(rèn)是由對(duì)象的地址轉(zhuǎn)換而來(lái)的

equals()方法還有5個(gè)默認(rèn)的原則:

自反性--->只要對(duì)象的不為null,x.equals(x)應(yīng)該返回的是true

一致性--->只要對(duì)象沒(méi)有被修改,那么多次調(diào)用還是返回對(duì)應(yīng)的結(jié)果!

傳遞性--->x.equals(y)y.equals(z)都返回true,那么可以得出:x.equals(z)返回true

對(duì)稱性--->x.equals(y)y.equals(x)結(jié)果應(yīng)該是相等的。

傳入的參數(shù)為null,返回的是false

為啥說(shuō)hashCode()以散列表為底層帶來(lái)性能的提升是很容易理解的。我們?cè)賮?lái)回顧一下HashMap的插入:

如果hash值都不相等,那么可以直接判斷該key是不相等的了!

2.1equals和hashCode方法重寫(xiě)

equals()方法默認(rèn)是比較對(duì)象的地址,使用的是==等值運(yùn)算符。但是按我們正常開(kāi)發(fā)來(lái)說(shuō),比較的是對(duì)象地址是沒(méi)有意義的。

一般地,如果我們有兩個(gè)Address對(duì)象,只要這兩個(gè)對(duì)象的省號(hào)、城市號(hào)、街道號(hào)相等,我們就認(rèn)為這兩個(gè)對(duì)象相等了!

2.2String實(shí)現(xiàn)的equals和hashCode方法

我們?cè)诔鯇W(xué)的時(shí)候可能就聽(tīng)過(guò)了:String已經(jīng)實(shí)現(xiàn)了equals和hashCode方法了。

這也就是為什么,我們可以直接使用String.equals()來(lái)判斷兩個(gè)字符串是否相等!

下面我們就來(lái)看看它的實(shí)現(xiàn)吧:

三、toString方法

接下來(lái)我們看看toString方法,也十分簡(jiǎn)單:

toString方法主要是用來(lái)標(biāo)識(shí)該對(duì)象的:

從上面的結(jié)果我們都可以看出來(lái):得出的結(jié)果我們并不能看到什么東西~

于是我們一般都重寫(xiě)toString(),那么打印出的結(jié)果就很方便我們調(diào)試了

    @Override
    public String toString() {
        return "Address{" +
                "provinceNo=" + provinceNo +
                ", cityNo=" + cityNo +
                ", streetNo=" + streetNo +
                "}";
    }

下面的結(jié)果看起來(lái)就好多了:

四、clone方法

我們也來(lái)看看它的頂部注釋:

看了上面的注釋我們可以總結(jié)以下的要點(diǎn)

clone方法用于對(duì)象的克隆,一般想要克隆出的對(duì)象是獨(dú)立的(與原有的對(duì)象是分開(kāi)的)

深拷貝指的是該對(duì)象的成員變量(如果是可變引用)都應(yīng)該克隆一份,淺拷貝指的是成員變量沒(méi)有被克隆一份

下面我們來(lái)看一下淺拷貝:拷貝了Employee對(duì)象,但是其成員變量hireday沒(méi)有被克隆出去,所以指向的還是同一個(gè)Date對(duì)象!

4.1clone用法

那么我們?nèi)绾慰寺?duì)象呢?無(wú)論是淺拷貝還是深拷貝都是這兩步:

克隆的對(duì)象要實(shí)現(xiàn)Cloneable接口

重寫(xiě)clone方法,最好修飾成public

淺拷貝:僅僅拷貝了Person對(duì)象,而date沒(méi)有拷貝!

public class Person implements Cloneable {

    // 可變的成員變量
    private Date date;

    @Override
    public Object clone() throws CloneNotSupportedException {

        return super.clone();
    }

}

深拷貝:不僅拷貝了Person對(duì)象,也拷貝了date成員變量

public class Person implements Cloneable {

    // 可變的成員變量
    public  Date date;

    @Override
    public Object clone() throws CloneNotSupportedException {


        // 拷貝Person對(duì)象
        Person person = (Person) super.clone();

        // 將可變的成員變量也拷貝
        person.date = (Date) date.clone();


        // 返回拷貝的對(duì)象
        return person;
    }

}
4.2clone疑問(wèn)進(jìn)一步學(xué)習(xí)protected

不知道有沒(méi)有人跟我有相同的疑問(wèn)

我只想要淺拷貝,能不能直接調(diào)用該對(duì)象.clone()來(lái)實(shí)現(xiàn)

比如我現(xiàn)在有個(gè)Address對(duì)象:

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;
    }
}

下面的代碼你們認(rèn)為如何?

    Address address = new Address(1, 2, 3);
    address.clone();

我們都知道:

protected修飾的類和屬性,對(duì)于自己、本包和其子類可見(jiàn)

可能會(huì)想clone()方法是定義在Object類上的(以protected來(lái)修飾),而我們自定義的Address對(duì)象隱式繼承著Object(所有的對(duì)象都是Object的子類),那么子類調(diào)用Object以protected來(lái)修飾clone()是完全沒(méi)問(wèn)題的

但是,IDE現(xiàn)實(shí)告訴我,這編譯就不通過(guò)了!

出現(xiàn)錯(cuò)誤的原因我立馬就想到:是不是我對(duì)protected修飾符出現(xiàn)了偏差?

protected修飾的類和屬性,對(duì)于自己、本包和其子類可見(jiàn),這句話本身是沒(méi)有錯(cuò)的。但是還需要補(bǔ)充:對(duì)于protected的成員或方法,要分子類和超類是否在同一個(gè)包中。與基類不在同一個(gè)包中的子類,只能訪問(wèn)自身從基類繼承而來(lái)的受保護(hù)成員,而不能訪問(wèn)基類實(shí)例本身的受保護(hù)成員。

上面的代碼就錯(cuò)在:Address與Object不是在同一個(gè)包下的,而Address直接訪問(wèn)了Object的clone方法。這是不行的。

下面我截兩張圖再來(lái)給你們看看(看完圖再看上面的描述,就能理解了):

圖片來(lái)源和更多的展開(kāi)閱讀:https://blog.csdn.net/wangyanguiyiyang/article/details/49800493

五、wait和notify方法

wait和notify方法其實(shí)就是Java給我們提供讓線程之間通信的API。

按照慣例我們還是來(lái)看注釋怎么說(shuō)吧:

wait方法:

notify方法:

notifyAll()方法:

看完上面的注釋我們可以總結(jié)以下的要點(diǎn)

無(wú)論是wait、notify還是notifyAll()都需要由監(jiān)聽(tīng)器對(duì)象(鎖對(duì)象)來(lái)進(jìn)行調(diào)用

簡(jiǎn)單來(lái)說(shuō):他們都是在同步代碼塊中調(diào)用的,否則會(huì)拋出異常!

notify()喚醒的是在等待隊(duì)列的某個(gè)線程(不確定會(huì)喚醒哪個(gè)),notifyAll()喚醒的是等待隊(duì)列所有線程

導(dǎo)致wait()的線程被喚醒可以有4種情況

該線程被中斷

wait()時(shí)間到了

notify()喚醒

notifyAll()喚醒

調(diào)用wait()的線程會(huì)釋放掉鎖

其實(shí)總結(jié)完上面的并不會(huì)有比較深刻的印象,可以嘗試著回答幾個(gè)問(wèn)題來(lái)加深對(duì)wait()notify()的理解。

5.1為什么wait和notify在Object方法上?

從一開(kāi)始我們就說(shuō)了:wait()notify()是Java給我們提供線程之間通信的API,既然是線程的東西,那什么是在Object類上定義,而不是在Thread類上定義呢?

因?yàn)槲覀兊?strong>鎖是對(duì)象鎖【要是忘記的同學(xué)可回顧:Java鎖機(jī)制了解一下】,每個(gè)對(duì)象都可以成為鎖。讓當(dāng)前線程等待某個(gè)對(duì)象的鎖,當(dāng)然應(yīng)該通過(guò)這個(gè)對(duì)象來(lái)操作了

鎖對(duì)象是任意的,所以這些方法必須定義在Object類中

5.2notify方法調(diào)用后,會(huì)發(fā)生什么?

上面已經(jīng)說(shuō)了,notify會(huì)喚醒某個(gè)處于等待隊(duì)列的線程。

但是要注意的是:

notify方法調(diào)用后,被喚醒的線程不會(huì)立馬獲得到鎖對(duì)象。而是等待notify的synchronized代碼塊執(zhí)行完之后才會(huì)獲得鎖對(duì)象

5.3sleep和wait有什么區(qū)別?

Thread.sleep()Object.wait()二者都可以暫停當(dāng)前線程,釋放CPU控制權(quán)。

主要的區(qū)別在于Object.wait()在釋放CPU同時(shí),釋放了對(duì)象鎖的控制。

Thread.sleep()沒(méi)有對(duì)鎖釋放

參考資料:

https://blog.csdn.net/lingzhm/article/details/44940823

http://www.cnblogs.com/dolphin0520/p/3920385.html

https://www.cnblogs.com/eer123/p/7880789.html

https://www.jianshu.com/p/f4454164c017

六、finalize()方法

finalize()方法將在垃圾回收器清除對(duì)象之前調(diào)用,但該方法不知道何時(shí)調(diào)用,具有不定性

一般我們都不會(huì)重寫(xiě)它~

一個(gè)對(duì)象的finalize()方法只會(huì)被調(diào)用一次,而且finalize()被調(diào)用不意味著gc會(huì)立即回收該對(duì)象,所以有可能調(diào)用finalize()后,該對(duì)象又不需要被回收了,然后到了真正要被回收的時(shí)候,因?yàn)榍懊嬲{(diào)用過(guò)一次,所以不會(huì)調(diào)用finalize(),產(chǎn)生問(wèn)題。

參考資料:

https://segmentfault.com/q/1010000000094660

進(jìn)階的資料:

https://www.cnblogs.com/Smina/p/7189427.html

http://www.importnew.com/23913.html

https://zhuanlan.zhihu.com/p/29522201

https://zhuanlan.zhihu.com/p/25698745

七、總結(jié)

總的來(lái)說(shuō)也算是把Object看了一遍了,不至于一下子把它的方法給忘了~~~在學(xué)習(xí)的過(guò)程中也遇到過(guò)問(wèn)題,最明顯的是對(duì)protected修飾符又加深了一次理解。

參考資料:

《Java核心技術(shù)卷一》

如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y。為了大家方便,剛新建了一下qq群:742919422,大家也可以去交流交流。謝謝支持了!希望能多介紹給其他有需要的朋友

文章的目錄導(dǎo)航

https://zhongfucheng.bitcron.com/post/shou-ji/wen-zhang-dao-hang

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/71104.html

相關(guān)文章

  • 你真會(huì)用setTimeout嗎?

    摘要:什么交互都處理不了怎么辦簡(jiǎn)化復(fù)雜度復(fù)雜邏輯后端處理的多線程上面都是的做法,但是也是處理這種問(wèn)題的一把好手。換一種思路,上面就是利用實(shí)現(xiàn)一種偽多線程的概念。 教科書(shū)里面的setTimeout 定義很簡(jiǎn)單 setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。 廣泛應(yīng)用場(chǎng)景 定時(shí)器,輪播圖,動(dòng)畫(huà)效果,自動(dòng)滾動(dòng)等等 上面一些應(yīng)該是setTimeout在大家心中的樣子...

    jsyzchen 評(píng)論0 收藏0
  • 再談閉包-詞法作用域

    摘要:權(quán)威指南第六版關(guān)于閉包的說(shuō)明采用詞法作用域,也就是說(shuō)函數(shù)的執(zhí)行依賴于變量的作用域,這個(gè)作用域是在函數(shù)定義時(shí)決定的,而不是函數(shù)調(diào)用時(shí)決定的。閉包這個(gè)術(shù)語(yǔ)的來(lái)源指函數(shù)變量可以被隱藏于作用域鏈之內(nèi),因此看起來(lái)是函數(shù)將變量包裹了起來(lái)。 最近打算換工作,所以參加了幾次面試(國(guó)內(nèi)比較知名的幾家互聯(lián)網(wǎng)公司)。在面試的過(guò)程中每當(dāng)被問(wèn)起閉包,我都會(huì)說(shuō)閉包是作用域的問(wèn)題?令人驚訝的是幾乎無(wú)一例外的當(dāng)我提到...

    Ku_Andrew 評(píng)論0 收藏0
  • 線程池你真不來(lái)了解一下嗎?

    摘要:所以說(shuō)我們的線程最好是交由線程池來(lái)管理,這樣可以減少對(duì)線程生命周期的管理,一定程度上提高性能。線程池不接收新任務(wù),不處理已添加的任務(wù),并且會(huì)中斷正在處理的任務(wù)。當(dāng)所有的任務(wù)已終止,記錄的任務(wù)數(shù)量為,線程池會(huì)變?yōu)闋顟B(tài)。線程池徹底終止的狀態(tài)。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡(jiǎn)單 多線程三分鐘就可以入個(gè)門了! 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍...

    stdying 評(píng)論0 收藏0
  • 你真的弄明白 new 了嗎

    摘要:如果構(gòu)造函數(shù)有返回值呢一般情況下構(gòu)造函數(shù)沒(méi)有返回值,但是我們依舊可以得到該對(duì)象的實(shí)例如果構(gòu)造函數(shù)有返回值,憑直覺(jué)來(lái)說(shuō)情況應(yīng)該會(huì)不一樣。歡迎光臨小弟博客我的博客原文你真的弄明白了嗎參考再談面向?qū)ο缶幊痰膶?shí)例化與繼承請(qǐng)停止使用關(guān)鍵字 好久沒(méi)有寫(xiě)點(diǎn)東西了,總覺(jué)得自己應(yīng)該寫(xiě)點(diǎn)牛逼的,卻又不知道如何下筆。既然如此,還是回歸最基本的吧,今天就來(lái)說(shuō)一說(shuō)這個(gè)new。關(guān)于javascript的new關(guān)鍵...

    tolerious 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<