概述
Object類是類層次結(jié)構(gòu)的根,Java中所有的類從根本上都繼承自這個類森逮。Object類是Java中唯一沒有父類的類榨婆。其他所有的類,包括標(biāo)準(zhǔn)容器類褒侧,比如數(shù)組良风,都繼承了Object類中的方法。
Object類位于java.lang包中闷供,java.lang包包含著Java最基礎(chǔ)和核心的類烟央,在編譯時(shí)會自動導(dǎo)入。Object類沒有定義屬性歪脏,一共有13個方法疑俭,具體的類定義結(jié)構(gòu)如下圖:
Object類中的方法
Java中的每個類都具有定義在Object類中的這些方法。
構(gòu)造方法
public Object()
大部分情況下婿失,Java中通過形如 new A(args..)形式創(chuàng)建一個屬于該類型的對象钞艇。其中A即是類名,A(args..)即此類定義中相對應(yīng)的構(gòu)造函數(shù)豪硅。通過此種形式創(chuàng)建的對象都是通過類中的構(gòu)造函數(shù)完成哩照。為體現(xiàn)此特性,Java中規(guī)定:在類定義過程中懒浮,對于未定義構(gòu)造函數(shù)的類飘弧,默認(rèn)會有一個無參數(shù)的構(gòu)造函數(shù),作為所有類的基類砚著,Object類自然要反映出此特性次伶,在源碼中,未給出Object類構(gòu)造函數(shù)定義稽穆,但實(shí)際上冠王,此構(gòu)造函數(shù)是存在的。
當(dāng)然秧骑,并不是所有的類都是通過此種方式去構(gòu)建版确,也自然的扣囊,并不是所有的類構(gòu)造函數(shù)都是public。
private static native void registerNatives();
registerNatives函數(shù)前面有native關(guān)鍵字修飾绒疗,Java中侵歇,用native關(guān)鍵字修飾的函數(shù)表明該方法的實(shí)現(xiàn)并不是在Java中去完成,而是由C/C++去完成吓蘑,并被編譯成了.dll惕虑,由Java去調(diào)用。方法的具體實(shí)現(xiàn)體在dll文件中磨镶,對于不同平臺溃蔫,其具體實(shí)現(xiàn)應(yīng)該有所不同。用native修飾琳猫,即表示操作系統(tǒng)伟叛,需要提供此方法,Java本身需要使用脐嫂。具體到registerNatives()方法本身统刮,其主要作用是將C/C++中的方法映射到Java中的native方法,實(shí)現(xiàn)方法命名的解耦账千。
protected Object clone()
Creates and returns a copy of this object.
Object類中的說明是:
protected Object clone() throws CloneNotSupportedException
這個方法比較特殊:
首先侥蒙,使用這個方法的類必須實(shí)現(xiàn)java.lang.Cloneable接口,否則會拋出CloneNotSupportedException異常匀奏。
Cloneable接口中不包含任何方法,所以實(shí)現(xiàn)它時(shí)只要在類聲明中加上implements語句即可娃善。
第二個比較特殊的地方在于這個方法是protected修飾的论衍,覆寫clone()方法的時(shí)候需要寫成public,才能讓類外部的代碼調(diào)用会放。
public final native Class<?> getClass();
getClass()也是一個native方法饲齐,返回的是此Object對象的類對象/運(yùn)行時(shí)類對象Class<?>。效果與Object.class相同咧最。
首先解釋下"類對象"的概念:在Java中,類是是對具有一組相同特征或行為的實(shí)例的抽象并進(jìn)行描述御雕,對象則是此類所描述的特征或行為的具體實(shí)例矢沿。作為概念層次的類,其本身也具有某些共同的特性酸纲,如都具有類名稱捣鲸、由類加載器去加載,都具有包闽坡,具有父類栽惶,屬性和方法等愁溜。于是,Java中有專門定義了一個類外厂,Class冕象,去描述其他類所具有的這些特性,因此汁蝶,從此角度去看渐扮,類本身也都是屬于Class類的對象。為與經(jīng)常意義上的對象相區(qū)分掖棉,在此稱之為"類對象"墓律。
boolean equals(Object obj)
Indicates whether some other object is "equal to" this one.
“==”運(yùn)算符判斷兩個引用是否指向同一個對象。==表示的是變量值完成相同(對于基礎(chǔ)類型幔亥,地址中存儲的是值耻讽,引用類型則存儲指向?qū)嶋H對象的地址);
equals表示的是對象的內(nèi)容完全相同帕棉,此處的內(nèi)容多指對象的特征/屬性齐饮。
對于Object類的equals()方法來說,它判斷調(diào)用equals()方法的引用于傳進(jìn)來的引用是否一致笤昨,即這兩個引用是否指向的是同一個對象祖驱。
Object類中的equals()方法如下:
public boolean equals(Object obj) {
return (this == obj);
}
即Object類中的equals()方法等價(jià)于==。
只有當(dāng)繼承Object的類覆寫(override)了equals()方法之后瞒窒,繼承類實(shí)現(xiàn)了用equals()方法比較兩個對象是否相等捺僻,才可以說equals()方法與==的不同。
equals()方法需要具有如下特點(diǎn):
- 自反性(reflexive):任何非空引用x崇裁,x.equals(x)返回為true匕坯。
- 對稱性(symmetric):任何非空引用x和y,x.equals(y)返回true當(dāng)且僅當(dāng)y.equals(x)返回true拔稳。
- 傳遞性(transitive):任何非空引用x和y葛峻,如果x.equals(y)返回true,并且y.equals(z)返回true巴比,那么x.equals(z)返回true术奖。
- 一致性(consistent):兩個非空引用x和y,x.equals(y)的多次調(diào)用應(yīng)該保持一致的結(jié)果轻绞,(前提條件是在多次比較之間沒有修改x和y用于比較的相關(guān)信息)采记。
- 約定:對于任何非空引用x,x.equals(null)應(yīng)該返回為false政勃。
- 并且覆寫equals()方法時(shí)唧龄,應(yīng)該同時(shí)覆寫hashCode()方法,反之亦然奸远。
int hashCode()
Returns a hash code value for the object.
當(dāng)你覆寫(override)了equals()方法之后既棺,必須也覆寫hashCode()方法讽挟,反之亦然。
這個方法返回一個整型值(hash code value)丸冕,如果兩個對象被equals()方法判斷為相等耽梅,那么它們就應(yīng)該擁有同樣的hash code。
Object類的hashCode()方法為不同的對象返回不同的值晨仑,Object類的hashCode值表示的是對象的地址褐墅。
hashCode的一般性契約(需要滿足的條件)如下:
1.在Java應(yīng)用的一次執(zhí)行過程中,如果對象用于equals比較的信息沒有被修改洪己,那么同一個對象多次調(diào)用hashCode()方法應(yīng)該返回同一個整型值妥凳。應(yīng)用的多次執(zhí)行中,這個值不需要保持一致答捕,即每次執(zhí)行都是保持著各自不同的值逝钥。
2.如果equals()判斷兩個對象相等,那么它們的hashCode()方法應(yīng)該返回同樣的值拱镐。
3.并沒有強(qiáng)制要求如果equals()判斷兩個對象不相等艘款,那么它們的hashCode()方法就應(yīng)該返回不同的值。即沃琅,兩個對象用equals()方法比較返回false哗咆,它們的hashCode可以相同也可以不同。但是益眉,應(yīng)該意識到晌柬,為兩個不相等的對象產(chǎn)生兩個不同的hashCode可以改善哈希表的性能。
WHY?
其實(shí)郭脂,這主要體現(xiàn)在hashCode()方法的作用上年碘,其主要用于增強(qiáng)哈希表的性能装哆。
以集合類中绢要,以Set為例,當(dāng)新加一個對象時(shí)擅腰,需要判斷現(xiàn)有集合中是否已經(jīng)存在與此對象相等的對象莹弊,如果沒有hashCode()方法涤久,需要將Set進(jìn)行一次遍歷,并逐一用equals()方法判斷兩個對象是否相等箱硕,此種算法時(shí)間復(fù)雜度為o(n)拴竹。通過借助于hasCode方法,先計(jì)算出即將新加入對象的哈希碼剧罩,然后根據(jù)哈希算法計(jì)算出此對象的位置,直接判斷此位置上是否已有對象即可座泳。(注:Set的底層用的是Map的原理實(shí)現(xiàn))
String toString()
Returns a string representation of the object.
當(dāng)打印引用惠昔,如調(diào)用System.out.println()時(shí)幕与,會自動調(diào)用對象的toString()方法,打印出引用所指的對象的toString()方法的返回值镇防,因?yàn)槊總€類都直接或間接地繼承自O(shè)bject啦鸣,因此每個類都有toString()方法。
Object類中的toString()方法定義如下:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
wait(...) / notify() / notifyAll()
protected void finalize()
finalize方法主要與Java垃圾回收機(jī)制有關(guān)来氧。