比較原始類型的相等與比較兩個對象相等是不同的。假如數值5存放在兩個不同的int變量中,比較兩個變量是否相等將產生結果為 boolean 值 true: public class TestIntComparison { public static void main(String[] args) { int x = 5, y = 5; System.out.PRintln( "x == y yields " + (x == y)); } } TestIntComparison 產生以下輸出:
D:/>java TestIntComparison x == y yields true 相等操作符由于原始類型時比較的是它們的值。而用于對象時比較的是對象的引用而不是對象的實際內容。 您可能問:"這些引用都指向同一個對象么?" 為了說明清楚,請看下面只含有 tag 和 age 的 Dog 的又一版本:
class Dog { int tag; int age; public void setTag(int t) {tag=t;} public void setAge(int a) {age=a;} } 假如有兩只狗(dog),即使它們的內容都相同,用 == 操作符時它們并不相等。下面代碼段的輸出表明在用 "==" 時 a 和 b 并不相等:
Dog a = new Dog(); a.setTag(23129); a.setAge(7); Dog b = new Dog(); b.setTag(23129); b.setAge(7); if ( a==b ) { System.out.println("a is equal to b"); } else { System.out.println("a is not equal to b"); } 那么,應該怎么比較兩個對象的值而不是比較它們的引用呢?Java(TM) 編程語言有一個約定,方法 equals() 用來定義對象值相等。 類 Object 中定義了方法equals(),假如在其子類中沒有被重載,那么默認使用的就是它。 為了比較兩只狗(dog) a 和 b 的值,你應該重寫上面的比較部分:
if ( a.equals(b) ) { System.out.println("a is equals() to b"); } else { System.out.println("a is not equals() to b"); } 上面的代碼中,假如在 Dog 中沒有重載 equals() 方法,兩只狗依舊不等。因為 Object.equals() 實際模擬的是 == 操作符的功能。 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() 的參數類型是 Object 而不是 Dog 呢?因為你是在重載父類 Object 的方法 equals(),所以必須用相同的方法標記。但我們希望傳進的參數是另一只Dog,所以為了能夠訪問參數的字段需將其類型轉換為 Dog。 但是,由于 equals() 是在 Dog 中定義的,你必須檢查傳入的對象是否是一只 Dog,因為有人可能這樣用: fido.equals("blort"); 字符串 "blort" 也是一個 Object ,因此與 Dog 中 equals() 的標記是匹配的。equals() 的正確寫法是:
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 詢問 o 是否是 Dog (包括 Dog 的子類) 的實例。 字符串的比較引入了對象比較的最后一個問題,那就是 "abc"=="def" 表達式的值為 true 還是 false 呢?是false,因為他們是本質都不同的對象(顯而易見,他們的內容都不同)。但是,下面的表達式 "abc"=="abc" 是 true 還是 false 呢?不幸的是,這由編譯器決定。假如編譯器將對 "abc" 的兩個引用優化為一個對象而不是兩個對象,那么表達式的值為 true。但是,假如編譯器不做這種優化,表達式的值則應為 false! 假如你真的想判定兩個字符串在物理上是不是同一個對象,請用 equals() 方法: boolean b = "abc".equals("def"); // false boolean c = "abc".equals("abc"); // true