Object類及常用方法簡(jiǎn)介

Object類是一個(gè)特殊的類听系,是所有類的父類恳谎,是java中唯一沒(méi)有父類的類术浪,如果一個(gè)類沒(méi)有用extends明確指出繼承于某個(gè)類瓢对,那么它默認(rèn)繼承Object類。

1.獲取對(duì)象信息的方法:toString

public class Student {

    private String name = "Mary";
    private int age = 21;

    public static void main(String[] args) {
        Student student = new Student();

        System.out.println(student.toString());
    }
    
}

輸出結(jié)果

com.netty.test23.Student@24367013

toString()方法添吗,它用于返回標(biāo)識(shí)對(duì)象值的字符串沥曹。類名@內(nèi)存地址
隨處可見(jiàn)toString()的主要原因是:只要對(duì)象與一個(gè)字符串通過(guò)操作符“+”連接起來(lái),java編譯器就會(huì)自動(dòng)地調(diào)用toString方法碟联,以便獲得這個(gè)對(duì)象的字符串描述妓美。

2.equals()

判斷兩個(gè)對(duì)象是否相等的方法±鸱酰可以先判斷地址是否相等壶栋,再判斷值是否相等。自定義對(duì)象需要重寫(xiě)該方法普监,不然該方法就是對(duì)比地址是否相等贵试。

 public boolean equals(Object obj) {
        return (this == obj);
    }
  • 以上方法,很明顯是對(duì)兩個(gè)對(duì)象的地址值進(jìn)行比較(即比較引用是否相同)凯正。
    看下String中該方法的實(shí)現(xiàn)毙玻,先判斷地址是否相等,再判斷類型廊散、字符長(zhǎng)度桑滩,各個(gè)字符是否相等。
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
  • 很明顯允睹,這是進(jìn)行內(nèi)容的比較运准,而已經(jīng)不再是地址的比較。

3.hashCode()

返回當(dāng)前對(duì)象的hash code value缭受,這個(gè)類是用來(lái)支持一些hash table胁澳,例如HashMap。
它的性質(zhì)是:

  • 在一個(gè)Java應(yīng)用的執(zhí)行期間米者,如果一個(gè)對(duì)象提供給equals做比較的信息沒(méi)有被修改的話韭畸,該對(duì)象多次調(diào)用hashCode()方法,該方法必須始終如一返回同一個(gè)Integer
  • 如果兩個(gè)對(duì)象根據(jù)equals(Object)方法是相等的塘雳,那么調(diào)用二者各自的hashCode()方法必須產(chǎn)生同一個(gè)integer結(jié)果陆盘。
  • 并不要求根據(jù)equals(lava.lang.Object)方法不相等的兩個(gè)對(duì)象,調(diào)用二者各自的hashCode()方法必須產(chǎn)生不同的integer結(jié)果
    在集合查找時(shí)败明,hashcode能大大降低對(duì)象比較次數(shù),提高查找效率
    Java對(duì)象的equals()和hashCode()是這樣規(guī)定的:
  1. 相等(相同)的對(duì)象必須具有相等的哈希碼(或者散列碼)太防。
    解釋:想象一下妻顶,如果兩個(gè)java對(duì)象A和B酸员,A和B相等(equals結(jié)果為true),但A和B的哈希碼不同讳嘱,則A和B存入HashMap時(shí)的哈希碼計(jì)算得到的HashMap內(nèi)部數(shù)組位置索引可能不同幔嗦,那么A和B很有可能允許同時(shí)存入HashMap,顯然相等/相同的元素是不允許同時(shí)存入HashMap沥潭,HashMap不允許存放重復(fù)元素邀泉。
  2. 如果兩個(gè)對(duì)象的hashCode相同,他們并不一定相等钝鸽。
    解釋:也就是說(shuō)汇恤,不同對(duì)象的HashCode可能相同;假如兩個(gè)Java對(duì)象A和B拔恰,A和B不相等(equals結(jié)果為false)因谎,但A和B的哈希碼相等,將A和B都存入HashMap時(shí)會(huì)發(fā)生哈希沖突颜懊,也就是A和B存入在HashMap時(shí)會(huì)發(fā)生哈希沖突财岔,也就是A和B存放在HashMap內(nèi)部數(shù)組的位置索引相同,這是HashMap會(huì)在該位置建立一個(gè)鏈表河爹,將A和B串起來(lái)放在該位置匠璧,顯然,該情況不違反HashMap的使用原則咸这,是允許的夷恍。當(dāng)然,hash沖突越少越好炊苫,盡量采用好的hash算法以避免哈希沖突裁厅。
    所以,java對(duì)于equals方法和hashCode方法是這樣規(guī)定的:
1. 如果兩個(gè)對(duì)象相同侨艾,那么它們的hashCode值一定要相同执虹;
2. 如果兩個(gè)對(duì)象的hashCode相同,它們并一定相同(這里說(shuō)的對(duì)象相同指的是用equals方法比較)唠梨。
3. equals()相等的兩個(gè)對(duì)象袋励,hashCode()一定相等;equals()不相等的兩個(gè)對(duì)象当叭,卻并不能證明他們的hashCode()不相等茬故。
換句話說(shuō),equals()方法不相等的兩個(gè)對(duì)象蚁鳖,hashcode()有可能相等(我的理解是由于哈希碼在生成的時(shí)候產(chǎn)生沖突造成的)磺芭。反過(guò)來(lái),hashcode()不等醉箕,一定能推出equals()也不等钾腺;hashcode()相等徙垫,equals()可能相等,也可能不等放棒。

在object類中姻报,hashcode()方法是本地方法,返回的是對(duì)象的地址值间螟,而object類中的equals()方法比較的也是兩個(gè)對(duì)象的地址值吴旋,如果equals()相等,說(shuō)明兩個(gè)對(duì)象地址值也相等厢破,當(dāng)然hashcode()也就相等了荣瑟;在String類中,equals()返回的是兩個(gè)對(duì)象內(nèi)容的比較溉奕,當(dāng)兩個(gè)對(duì)象內(nèi)容相等時(shí)褂傀,Hashcode()方法根據(jù)String類的重寫(xiě)代碼的分析,也可知道hashcode()返回結(jié)果也會(huì)相等加勤。以此類推仙辟,可以知道Integer、Double等封裝類中經(jīng)過(guò)重寫(xiě)的equals()和hashcode()方法也同樣適合于這個(gè)原則鳄梅。當(dāng)然沒(méi)有經(jīng)過(guò)重寫(xiě)的類叠国,在繼承了object類的equals()和hashcode()方法后,也會(huì)遵守這個(gè)原則戴尸。

4. clone()

源碼

protected native Object clone() throws CloneNotSupportedException;

又源碼我們會(huì)發(fā)現(xiàn):
第一:Object類的clone()方法是一個(gè)native方法粟焊,native方法的效率一般來(lái)說(shuō)都是遠(yuǎn)高于java中的非native方法。這也解釋了為什么要用Object中的clone方法而不是先new一個(gè)類孙蒙,然后把原始對(duì)象中的信息復(fù)制到新對(duì)象中项棠,雖然這也實(shí)現(xiàn)了clone功能。
第二:Object類中的clone()方法被protected修飾符修飾挎峦。這也意味著如果要應(yīng)用clone()方法香追,必須繼承Object類,在java中所有的類是缺省繼承Object類的坦胶,也就不用關(guān)心這點(diǎn)了透典。然后重載clone()方法。這一點(diǎn)要考慮的是為了讓其他類能調(diào)用這個(gè)對(duì)象類的clone()方法顿苇,重載之后要把clone()方法的屬性設(shè)置為public.
第三:Object.clone()方法返回一個(gè)Object對(duì)象峭咒。我們必須進(jìn)行強(qiáng)制類型轉(zhuǎn)換才能得到我們需要的類型。

淺層復(fù)制與深層復(fù)制

淺層復(fù)制:被復(fù)制的對(duì)象的所有成員屬性都與原來(lái)的對(duì)象值相同纪岁,而所有的對(duì)其他對(duì)象的引用仍然指向原來(lái)的對(duì)象凑队。換言之,淺層復(fù)制僅僅復(fù)制所考慮的對(duì)象幔翰,而不復(fù)制它引用的對(duì)象顽决。

  • 當(dāng)某個(gè)類要復(fù)寫(xiě)clone方法時(shí)短条,要繼承Cloneable接口导匣。通常的克隆對(duì)象都是通過(guò)super.clone()方法來(lái)克隆對(duì)象才菠。
  • 淺拷貝就是拷貝一個(gè)對(duì)象的副本。若只需要復(fù)制對(duì)象的字段值(對(duì)于基本數(shù)據(jù)類型贡定,如:int,long,float等赋访,則復(fù)制值;對(duì)于復(fù)合數(shù)據(jù)類型僅復(fù)制該字段值缓待,如數(shù)組變量則復(fù)制地址蚓耽,對(duì)于對(duì)象變量則復(fù)制對(duì)象reference).
public class ShadowClone implements Cloneable {

    private int a;
    private int[] b;

    public Object clone() {
        ShadowClone sc = null;

        try {
            sc = (ShadowClone) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return sc;
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public int[] getB() {
        return b;
    }

    public void setB(int[] b) {
        this.b = b;
    }

    public static void main(String[] args) {
        ShadowClone c1 = new ShadowClone();

        c1.setA(100);
        c1.setB(new int[]{1000});

        System.out.println("克隆前c1: a=" + c1.getA() + " b=" + c1.getB()[0]);

        ShadowClone c2 = (ShadowClone) c1.clone();
        c2.setA(50);
        int[] a = c2.getB();
        a[0] = 5;
        c2.setB(a);

        System.out.println("克隆前c1:  a=" + c1.getA() + " b=" + c1.getB()[0]);
        System.out.println("克隆后c2:  a=" + c2.getA() + " b[0]=" + c2.getB()[0]);
    }
}

結(jié)果為:

克隆前c1: a=100 b=1000
克隆前c1:  a=100 b=5
克隆后c2:  a=50 b[0]=5

c1和c2的對(duì)象模型:


image.png
  • 可以看出,基本類型可以使用淺拷貝旋炒,而對(duì)于引用類型步悠,由于引用的是內(nèi)容相同,所以改變c2實(shí)例對(duì)象中的屬性就會(huì)影響到c1瘫镇。所以引用類型需要使用深拷貝鼎兽。另外,在開(kāi)發(fā)一個(gè)不可變類的時(shí)候铣除,如果這個(gè)不可變類中成員有引用類型谚咬,則就需要通過(guò)深拷貝來(lái)達(dá)到不可變的目的。
  • 需要注意:
    1. 希望能實(shí)現(xiàn)clone功能的CloneClass類實(shí)現(xiàn)了Cloneable接口尚粘,這個(gè)接口屬于java.lang 包择卦,java.lang包已經(jīng)被缺省的導(dǎo)入類中,所以不需要寫(xiě)成java.lang.Cloneable郎嫁。
    2. 重載了clone() 方法秉继。最后在clone()方法中調(diào)用了super.clone(),這也意味著無(wú)論clone類的繼承結(jié)構(gòu)是什么樣的泽铛,super.clone()直接或間接調(diào)用了java.lang.Object類的clone()方法
    3. Object類的clone()是一個(gè)native方法尚辑,native方法的效率一般來(lái)說(shuō)都是遠(yuǎn)高于java中的非native方法。這也解釋了為什么要用Object中clone()方法而不是先new一個(gè)類厚宰,然后把原始對(duì)象中的信息賦到新對(duì)象中腌巾,雖然這也實(shí)現(xiàn)了clone方法。對(duì)于第二點(diǎn)铲觉,也要 觀察Object類中的clone()還是一個(gè)protected屬性的方法澈蝙。這也意味著如果要應(yīng)用clone()方法,必須繼承Object類撵幽,在 Java中所有的類是缺省繼承Object類的灯荧,也就不用關(guān)心這點(diǎn)了。然后重載clone()方法盐杂。還有一點(diǎn)要考慮的是為了讓其它類能調(diào)用這個(gè)clone 類的clone()方法逗载,重載之后要把clone()方法的屬性設(shè)置為public哆窿。

深層復(fù)制:被復(fù)制對(duì)象的所有變量都含有與原來(lái)的對(duì)象相同的值,除去那些引用其他對(duì)象的變量厉斟。那么引用其他對(duì)象的變量將指向被復(fù)制過(guò)的新對(duì)象挚躯,而不是原有的那些被引用的對(duì)象。換言之擦秽,深層復(fù)制要復(fù)制的對(duì)象引用的對(duì)象都復(fù)制一遍码荔。

public class Student implements Cloneable {
    private String name;
    private int age;
    Professor pro;
    public Student(){}
    public Student(String name,int age,Professor pro){
        this.name=name;
        this.age=age;
        this.pro=pro;
    }
    public Object clone(){
        Student o=null;
        try {
            //Object中的clone()識(shí)別出你要復(fù)制的是哪一個(gè)對(duì)象。
            o=(Student)super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println(e.toString());
        }
        o.pro=(Professor)pro.clone();
        return o;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Professor getPro() {
        return pro;
    }
    public void setPro(Professor pro) {
        this.pro = pro;
    }
}
class Professor implements Cloneable{
    private String name;
    private int age;
    public Professor(){}
    public Professor(String name,int age){
        this.name=name;
        this.age=age;
    }
    public Object clone(){
        Object o=null;
        try {
            o=super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末感挥,一起剝皮案震驚了整個(gè)濱河市缩搅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌触幼,老刑警劉巖硼瓣,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異置谦,居然都是意外死亡堂鲤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門霉祸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)筑累,“玉大人,你說(shuō)我怎么就攤上這事丝蹭÷冢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵奔穿,是天一觀的道長(zhǎng)镜沽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)贱田,這世上最難降的妖魔是什么缅茉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮男摧,結(jié)果婚禮上蔬墩,老公的妹妹穿的比我還像新娘。我一直安慰自己耗拓,他們只是感情好拇颅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著乔询,像睡著了一般樟插。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天黄锤,我揣著相機(jī)與錄音搪缨,去河邊找鬼。 笑死鸵熟,一個(gè)胖子當(dāng)著我的面吹牛副编,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播旅赢,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼齿桃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了煮盼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤带污,失蹤者是張志新(化名)和其女友劉穎僵控,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鱼冀,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡报破,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了千绪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片充易。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖荸型,靈堂內(nèi)的尸體忽然破棺而出盹靴,到底是詐尸還是另有隱情,我是刑警寧澤瑞妇,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布稿静,位于F島的核電站,受9級(jí)特大地震影響辕狰,放射性物質(zhì)發(fā)生泄漏改备。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一蔓倍、第九天 我趴在偏房一處隱蔽的房頂上張望悬钳。 院中可真熱鬧,春花似錦偶翅、人聲如沸默勾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)灾测。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間媳搪,已是汗流浹背铭段。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秦爆,地道東北人序愚。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像等限,于是被迫代替她去往敵國(guó)和親爸吮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容