那么,應(yīng)該怎么比較兩個(gè)對(duì)象的值而不是比較它們的引用呢?Java(TM) 編程語(yǔ)言有一個(gè)約定,方法 equals() 用來(lái)定義對(duì)象值相等。 類(lèi) Object 中定義了方法equals(),如果在其子類(lèi)中沒(méi)有被重載,那么默認(rèn)使用的是它。 為了比較兩只狗(dog) a 和 b 的值,你應(yīng)該重寫(xiě)上面的比較部分:
if ( a.equals(b) ) {
System.out.println("a is equals() to b");
}
else {
System.out.println("a is not equals() to b");
}
上面的代碼中,如果在 Dog 中沒(méi)有重載 equals() 方法,兩只狗依舊不等。因?yàn)?Object.equals() 實(shí)際模擬的是 == 操作符的功能。 Dog 中 equals() 的定義很好懂:
class Dog {
int tag;
int age;
public void setTag(int t) {tag=t;}
public void setAge(int a) {age=a;}
public boolean equals(Object o) {
Dog d = (Dog)o;
if ( tag==d.tag && age==d.age ) {
return true;
}
return false;
}
}
為什么 equals() 的參數(shù)類(lèi)型是 Object 而不是 Dog 呢?因?yàn)槟闶窃谥剌d父類(lèi) Object 的方法 equals(),所以必須用相同的方法標(biāo)記。但我們希望傳進(jìn)的參數(shù)是另一只Dog,所以為了能夠訪問(wèn)參數(shù)的字段需將其類(lèi)型轉(zhuǎn)換為 Dog。
但是,由于 equals() 是在 Dog 中定義的,你必須檢查傳入的對(duì)象是否是一只 Dog,因?yàn)橛腥丝赡苓@樣用:
fido.equals("blort");
字符串 "blort" 也是一個(gè) Object ,因此與 Dog 中 equals() 的標(biāo)記是匹配的。equals() 的正確寫(xiě)法是:
public boolean equals(Object o) {
if ( o instanceof Dog ) {
Dog d = (Dog)o;
if ( tag==d.tag && age==d.age ) {
return true;
}
}
// false if not Dog or contents mismatched
return false;
}
操作符 instanceof 詢(xún)問(wèn) o 是否是 Dog (包括 Dog 的子類(lèi)) 的實(shí)例。
字符串的比較引入了對(duì)象比較的后一個(gè)問(wèn)題,那是
"abc"=="def"
表達(dá)式的值為 true 還是 false 呢?是false,因?yàn)樗麄兪潜举|(zhì)都不同的對(duì)象(顯而易見(jiàn),他們的內(nèi)容都不同)。但是,下面的表達(dá)式
"abc"=="abc"
是 true 還是 false 呢?不幸的是,這由編譯器決定。如果編譯器將對(duì) "abc" 的兩個(gè)引用優(yōu)化為一個(gè)對(duì)象而不是兩個(gè)對(duì)象,那么表達(dá)式的值為 true。但是,如果編譯器不做這種優(yōu)化,表達(dá)式的值則應(yīng)為 false!
如果你真的想判斷兩個(gè)字符串在物理上是不是同一個(gè)對(duì)象,請(qǐng)用 equals() 方法:
boolean b = "abc".equals("def"); // false
boolean c = "abc".equals("abc"); // true
根據(jù)上面得方法,然后用assertTrue即可完成兩個(gè)對(duì)象的比較。