Java中Object類的十二種方法及作用

Object是Java所有類的基類迈嘹,是整個(gè)類繼承結(jié)構(gòu)的頂端碰酝,我們幾乎每次都需要使用到它丐黄。
Object的12種方法分別是:registerNatives()绊序、getClass()纷宇、hashCode()夸盟、equals()clone()像捶、toString()上陕、wait()桩砰、wait(long)wait(long,int)释簿、notify()亚隅、notifyAll()finalize()庶溶。下面對(duì)這些方法做一個(gè)總結(jié)歸納煮纵。

registerNatives()

private static native void registerNatives();
static {
   registerNatives();
}       

這個(gè)方法是一個(gè)注冊(cè)本地方法,由JVM實(shí)現(xiàn)渐尿,底層是C/C++實(shí)現(xiàn)的醉途,由代碼我們可以發(fā)現(xiàn)一個(gè)問題,為什么要使用靜態(tài)方法砖茸,還要放在靜態(tài)塊中呢隘擎?
原因是類初始化的順序是:
父類–靜態(tài)變量/父類–靜態(tài)初始化塊
子類–靜態(tài)變量/子類–靜態(tài)初始化塊
父類–變量/父類–初始化塊
父類–構(gòu)造器
子類–變量/子類–初始化塊
子類–構(gòu)造器
放入靜態(tài)代碼塊中保證了父類的類變量及方法的初始化一定先于子類,所以當(dāng)子類調(diào)用響應(yīng)native方法凉夯,比如計(jì)算hashCode()時(shí)货葬,一定可以保證能夠調(diào)用到JVM的native方法。

getClass()

public final native Class<?> getClass();

這是一個(gè) public的方法劲够,我們可以直接通過對(duì)象調(diào)用震桶。
類加載的第一階段類的加載就是將 .class文件加載到內(nèi)存,并生成一個(gè) java.lang.Class對(duì)象的過程征绎。 getClass()方法就是獲取這個(gè)對(duì)象蹲姐,這是當(dāng)前類的對(duì)象在運(yùn)行時(shí)類的所有信息的集合。這個(gè)方法是反射三種方式之一(類名.class人柿、對(duì)象.getClass柴墩、Class.forName("全類名"))。

hashCode()

public native int hashCode();

這是一個(gè) public的方法凫岖,所以子類可以重寫它江咳。這個(gè)方法返回當(dāng)前對(duì)象的 hashCode值,這個(gè)值是一個(gè)整數(shù)范圍內(nèi)的 (-2^31~2^31-1)數(shù)字哥放。
對(duì)于 hashCode有以下幾點(diǎn)約束:

  1. 在 Java應(yīng)用程序執(zhí)行期間歼指,在對(duì)同一對(duì)象多次調(diào)用 hashCode 方法時(shí),必須一致地返回相同的整數(shù)甥雕,前提是將對(duì)象進(jìn)行 equals 比較時(shí)所用的信息沒有被修改踩身;
  2. 如果兩個(gè)對(duì)象 x.equals(y) 方法返回 true,則 x社露、 y這兩個(gè)對(duì)象的 hashCode必須相等惰赋。
  3. 如果兩個(gè)對(duì)象 x.equals(y) 方法返回 false,則 x、 y這兩個(gè)對(duì)象的 hashCode可以相等也可以不等赁濒。但是轨奄,為不相等的對(duì)象生成不同整數(shù)結(jié)果可以提高哈希表的性能。
  4. 默認(rèn)的 hashCode是將內(nèi)存地址轉(zhuǎn)換為的 hash值拒炎,重寫過后就是自定義的計(jì)算方式挪拟;也可以通過 System.identityHashCode(Object)來返回原本的 hashCode。

equals()

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

用于比較當(dāng)前對(duì)象與目標(biāo)對(duì)象是否相等击你,默認(rèn)是比較引用是否指向同一對(duì)象玉组。為 public方法,子類可重寫丁侄。

為什么需要重寫 equals方法惯雳?

因?yàn)槿绻恢貙慹quals方法,當(dāng)將自定義對(duì)象放到 map或者 set中時(shí)鸿摇;如果這時(shí)兩個(gè)對(duì)象的 hashCode相同石景,就會(huì)調(diào)用 equals方法進(jìn)行比較,這個(gè)時(shí)候會(huì)調(diào)用 Object中默認(rèn)的 equals方法拙吉,而默認(rèn)的 equals方法只是比較了兩個(gè)對(duì)象的引用是否指向了同一個(gè)對(duì)象潮孽,顯然大多數(shù)時(shí)候都不會(huì)指向,這樣就會(huì)將重復(fù)對(duì)象存入 map或者 set中筷黔。這就破壞了 map與 set不能存儲(chǔ)重復(fù)對(duì)象的特性往史,會(huì)造成內(nèi)存溢出。

重寫 equals方法的幾條約定:

  1. 自反性:即 x.equals(x)返回 true佛舱, x不為 null椎例;
  2. 對(duì)稱性:即 x.equals(y)與 y.equals(x)的結(jié)果相同, x與 y不為 null请祖;
  3. 傳遞性:即 x.equals(y)結(jié)果為 true, y.equals(z)結(jié)果為 true订歪,則 x.equals(z)結(jié)果也必須為 true;
  4. 一致性:即 x.equals(y)返回 true或 false损拢,在未更改 equals方法使用的參數(shù)條件下,多次調(diào)用返回的結(jié)果也必須一致撒犀。 x與 y不為 null福压。
  5. 如果 x不為 null, x.equals(null)返回 false。

clone()

protected native Object clone() throws CloneNotSupportedException;

此方法返回當(dāng)前對(duì)象的一個(gè)副本或舞。

這是一個(gè) protected方法荆姆,提供給子類重寫。但需要實(shí)現(xiàn) Cloneable接口映凳,這是一個(gè)標(biāo)記接口胆筒,如果沒有實(shí)現(xiàn),當(dāng)調(diào)用 object.clone()方法,會(huì)拋出 CloneNotSupportedException仆救。

@Override    
protected CloneTest clone() throws CloneNotSupportedException
{
    return (CloneTest) super.clone();
}

那如果我們要進(jìn)行深拷貝怎么辦呢抒和?
答案是:如果成員變量是引用類型,想實(shí)現(xiàn)深拷貝彤蔽,則成員變量也要實(shí)現(xiàn) Cloneable接口摧莽,重寫 clone方法。

toString()

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

這是一個(gè) public方法顿痪,子類可重寫镊辕,建議所有子類都重寫 toString方法,默認(rèn)的 toString方法蚁袭,只是將當(dāng)前類的全限定性類名 +@+十六進(jìn)制的 hashCode值征懈。

wait()/ wait(long)/ wait(long,int)

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


public final void wait() throws InterruptedException {
        wait(0);
}

這三個(gè)方法是用來線程間通信用的,作用是阻塞當(dāng)前線程揩悄,等待其他線程調(diào)用 notify()/notifyAll()方法將其喚醒卖哎。這些方法都是 publicfinal的,不可被重寫虏束。

注意:

  1. 此方法只能在當(dāng)前線程獲取到對(duì)象的鎖監(jiān)視器之后才能調(diào)用棉饶,否則會(huì)拋出 IllegalMonitorStateException異常。
  2. 調(diào)用 wait方法镇匀,線程會(huì)將鎖監(jiān)視器進(jìn)行釋放照藻;而 Thread.sleep,Thread.yield()并不會(huì)釋放鎖汗侵。
  3. wait方法會(huì)一直阻塞幸缕,直到其他線程調(diào)用當(dāng)前對(duì)象的 notify()/notifyAll()方法將其喚醒;而 wait(long)是等待給定超時(shí)時(shí)間內(nèi)(單位毫秒)晰韵,如果還沒有調(diào)用 notify()/nofiyAll()會(huì)自動(dòng)喚醒发乔; wait(long,int)如果第二個(gè)參數(shù)大于 0并且小于 999999,則第一個(gè)參數(shù) +1作為超時(shí)時(shí)間雪猪;

notify()/notifyAll()

public final native void notify();

public final native void notifyAll();

前面說了栏尚,如果當(dāng)前線程獲得了當(dāng)前對(duì)象鎖,調(diào)用 wait方法只恨,將鎖釋放并阻塞译仗;這時(shí)另一個(gè)線程獲取到了此對(duì)象鎖,并調(diào)用此對(duì)象的 notify()/notifyAll()方法將之前的線程喚醒官觅。這些方法都是 publicfinal的纵菌,不可被重寫。

publicfinalnativevoidnotify(); 隨機(jī)喚醒之前在當(dāng)前對(duì)象上調(diào)用 wait方法的一個(gè)線程
publicfinalnativevoidnotifyAll(); 喚醒所有之前在當(dāng)前對(duì)象上調(diào)用 wait方法的線程

注意:調(diào)用 notify()后休涤,阻塞線程被喚醒咱圆,可以參與鎖的競爭,但可能調(diào)用 notify()方法的線程還要繼續(xù)做其他事,鎖并未釋放序苏,所以我們看到的結(jié)果是手幢,無論 notify()是在方法一開始調(diào)用,還是最后調(diào)用杠览,阻塞線程都要等待當(dāng)前線程結(jié)束才能開始弯菊。

finalize

 protected void finalize() throws Throwable { }

此方法是在垃圾回收之前,JVM會(huì)調(diào)用此方法來清理資源踱阿。此方法可能會(huì)將對(duì)象重新置為可達(dá)狀態(tài)管钳,導(dǎo)致JVM無法進(jìn)行垃圾回收。永遠(yuǎn)不要主動(dòng)調(diào)用某個(gè)對(duì)象的 finalize()方法软舌,該方法由垃圾回收機(jī)制自己調(diào)用才漆;

感謝codesheep!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市佛点,隨后出現(xiàn)的幾起案子醇滥,更是在濱河造成了極大的恐慌,老刑警劉巖超营,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸳玩,死亡現(xiàn)場離奇詭異,居然都是意外死亡演闭,警方通過查閱死者的電腦和手機(jī)不跟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來米碰,“玉大人窝革,你說我怎么就攤上這事÷雷” “怎么了虐译?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吴趴。 經(jīng)常有香客問我漆诽,道長,這世上最難降的妖魔是什么锣枝? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任厢拭,我火速辦了婚禮,結(jié)果婚禮上惊橱,老公的妹妹穿的比我還像新娘蚪腐。我一直安慰自己箭昵,他們只是感情好税朴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般正林。 火紅的嫁衣襯著肌膚如雪泡一。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天觅廓,我揣著相機(jī)與錄音鼻忠,去河邊找鬼。 笑死杈绸,一個(gè)胖子當(dāng)著我的面吹牛帖蔓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瞳脓,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼塑娇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了劫侧?” 一聲冷哼從身側(cè)響起埋酬,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烧栋,沒想到半個(gè)月后写妥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡审姓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年珍特,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邑跪。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡次坡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出画畅,到底是詐尸還是另有隱情砸琅,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布轴踱,位于F島的核電站症脂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淫僻。R本人自食惡果不足惜诱篷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雳灵。 院中可真熱鬧棕所,春花似錦、人聲如沸悯辙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至针贬,卻和暖如春击费,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桦他。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工蔫巩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人快压。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓圆仔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蔫劣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荧缘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355