Java判斷兩個對象是否相等的規則
Object類中的equals方法用於檢測一個對象是否等於另外一個對象。在Object類中,這個方法將判斷兩個對象是否具有相同的引用。如果兩個對象具有相同的引用,它們一定是相等的。從這點上看,將其作為默認操作也是合情合理的。然而對於多數類來說,這種判斷並沒有什麽意義。例如,采用這種方式比較兩個PrintStream對象是否相等就完全沒有意義。然而,經常需要檢測兩個對象狀態的相等性,如果兩個對象的狀態相等,就認為這兩個對象是相等的。
例如,如果兩個雇員對象的姓名、薪水和雇傭日期都一樣,就認為它們是相等的(在實際的雇員數據庫中,比較id更有意義,利用下面這個示例演示equals方法的實現機制)。
public boolean equals(Object otherObject) { Employee other = (Employee)otherObject; //a quick test to see if the objects are identical if (this == otherObject) return true; //must reture false if the explicit parameter is null if (otherObject == null) returnfalse; //if the classes don‘t match, they can‘t be equal if (getClass() != otherObject.getClass()) return false; //test whether the fields have identical values return name.equals(other.name) && salary== other.salary&& hireDay.equals(other.hireDay); }
getClass方法將返回一個對象所屬的類。在檢測中,只有在兩個對象屬於同一個類時,才有可能相等。
Java語言規範要求equals方法具有下面的特性:
1)自反性:對於任何非空引用x, x.equals(x)應該返回true。
2)對稱性:對於任何引用x和y,當且僅當y.equals(x)返回true,x.equals(y)也應該返回true。
3)傳遞性:對於任何引用x, y 和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也應該返回 true。
4)一致性:如果x和y引用的對象沒有發生變化,反復調用x.equals(y)應該返回同樣的結果。
5)對於任意非空引用x, x.equals(null)應該返回false。
以下是編寫完美的equals方法的建議:
1、顯式參數命名為otherObject,稍後需要將它轉換成另一個叫做other的變量。
2、檢測this與otherObject是否引用同一個對象:
if(this == otherObject) return true;
這條語句只是一個優化。實際上,這是一種經常采用的形式。因為計算這個等式要比一個一個地比較類中的域所付出的代價要小的 多。
3、檢測otherObject是否為null,如果為null,返回false。這項檢測是很必要的。
if(otherObject == null) return false;
4、比較this與otherObject是否屬於同一個類。如果 equals的語義在每個子類中有所改變,就使用getClass檢測:
if(getClass()!=otherObject.getClass()) return false;
如果所有的子類都擁有統一的語義,就使用instanceof檢測:
if(!(otherObject instanceof ClassName) ) return false;
5、將otherObject轉換為相應的類類型變量:
ClassName other = (ClassName)otherObject;
6、現在開始對所有需要比較的域進行比較了。使用==比較基本類型域,使用equals比較對象域。如果所有的域都匹配,就返回true;否 則返回false。
return field1 == other.field1 && Object.equals(field2, other,field2)&&...
如果在子類中重新定義equals,就要在其中包含調用super.equals(other).
Java判斷兩個對象是否相等的規則