Object類物件剖析

shuaishuai3409發表於2016-08-17

Object是所有類的父類,具備所有物件都能用的共性內容,下面介紹下常用的四種方法。


1 boolean equals(Object obj)
顧名思義,這是比較物件是否相等的方法(向上轉型)。大家周知道,”==“是用來比較兩個物件地址是否相同的方法,那麼equals是比較地址還是內容呢?我們通過Object原始碼來分析下。

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

通過原始碼可以知道,Object類本質上也是通過”==“來比較,比較的也是地址。所以,通過如下程式碼,我們可以清楚知道main函式中均返回情況。

class Car{
    int battery;
    car(int bat){this.battery=bat;}
}
class Dog{
    int age;
    Dog(int age){this.age=age;}
}
public static void main(){
    Car c1=new Car(10);
    Car c2=new Car(10);
    Dog d1=new Dog(10);
    System.out.println(c1==c2);//false
    System.out.println(c1.equals(c2));//false
}

所以,按Object類中的equals()方法,其本質和”==“相同,有種雞肋的感覺。若想只比較物件內容是否相同,需要其子類對equals方法重寫。String 、Math、還有Integer、Double等就進行了重寫,所以equals比較的就是內容,也可以自己重寫。

public boolean equals(Object obj){
    Car c=(Car)obj;
    return this.battery==c.battery;
}
system.out.println(c1.equals(c2))//true

2 public native int hasCode()

關鍵字native表示本地方法,可以理解為java呼叫非java語言的介面,比如java需要與底層如os或硬體交換資訊時,就可以使用native方法。hasCode方法返回物件的雜湊碼值,先給兩個例子看下。

system.out.println(c1);//輸出:Car@32ed11,@後面就是物件轉換的hash值
system.out.println(Integer.toHexString.(c1.hasCode()));//輸出:32ed11;hascode返回十進位制數,需要轉換成十六進位制

在java語言裡,基本上重寫equals方法後,就有必要重寫hasCode()方法,為什麼呢?

從java判斷兩個物件是否相等的規則說起,在java的集合中,存在兩個規範:
規範1:若重寫equals(Object obj)方法,有必要重寫hashcode()方法,確保通過equals(Object obj)方法判斷結果為true的兩個物件具備相等的hashcode()返回值。說得簡單點就是:“如果兩個物件相同,那麼他們的hashcode應該 相等”。不過請注意:這個只是規範,如果你非要寫一個類讓equals(Object obj)返回true而hashcode()返回兩個不相等的值,編譯和執行都是不會報錯的。不過這樣違反了Java規範,程式也就埋下了BUG。
規範2:如果equals(Object obj)返回false,即兩個物件“不相同”,並不要求對這兩個物件呼叫hashcode()方法得到兩個不相同的數。說的簡單點就是:“如果兩個物件不相同,他們的hashcode可能相同”。
根據這兩個規範,可以得到如下推論:
1> 如果兩個物件equals,Java執行時環境會認為他們的hashcode一定相等。
2> 如果兩個物件不equals,他們的hashcode有可能相等。
3> 如果兩個物件hashcode相等,他們不一定equals。
4> 如果兩個物件hashcode不相等,他們一定不equals。

一般來說,如果你要把一個類的物件放入容器中,那麼通常要為其重寫equals()方法,讓他們比較內容而不是地址值,要放到有序容器中,需要重寫compareTo()方法;特別地,如果要把你的類的物件放入雜湊(hashMap,hashSet)中,那麼還要重寫hashCode()方法。

記住String物件的三種比較方式:

==記憶體比較:直接對比兩個引用所指向的記憶體值,精確簡潔直接明瞭。

equals字串值比較:比較兩個引用所指物件字面值是否相等。

hashCode字串數值化比較:將字串數值化。兩個引用的hashCode相同,不保證記憶體一定相同,不保證字面值一定相同。


3 class<?>getClass()方法

反射用,每個Class,都含有getClass方法,用來返回位元組碼檔案物件(Car.class)。而程式執行後,先裝載Car.Class位元組碼檔案,然後在對記憶體中產生Car.Class位元組碼物件,然後用該位元組碼物件生成Car物件,而且這些Car物件的地址都是相同的,因為都是基於位元組碼檔案物件地址產生的(引用)。

class cla1=c1.getClass();
class cla2=c2.getClass();
System.out.println(c1==c2);//true,

4 String toString()方法

該方法用來返回物件字串。

system.out.println(c1);
system.out.println(c1.toString());//兩者效果是相同的

相關文章