[英]Why this two simple objects are not equal?
我有一堂課:
public class School {
private String name;
private int id;
private boolean isOpen;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isOpen() {
return isOpen;
}
public void setOpen(boolean isOpen) {
this.isOpen = isOpen;
}
}
然后我創建了兩個School實例,並比較了兩個實例的相等性:
public static void main(String[] args) {
//school1
School school1 = new School();
school1.setId(1);
school1.setName("schoolOne");
//school2
School school2 = new School();
school2.setId(1);
school2.setName("schoolOne");
//result is false , why?
System.out.println("school1 == school2 ? " + school1.equals(school2));
}
即使我設置相同的id
和name
,以school1
& school2
實例,但school1.equals(school2)
返回false,為什么呢?
您必須覆蓋equals(Object)
方法:
把它放在你的學校課堂上:
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (other == null || !(other instanceof School)) return false;
School school = (School) other;
if (school.id != this.id) return false;
if (!(school.name.equals(this.name))) return false;
if (school.isOpen != this.isOpen) return false;
if (!(school.hashCode().equals(this.hashCode()))) return false;
return true;
}
如果你要這樣做,也可以覆蓋hashCode()
方法。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) id;
result = prime * result + (name != null ? name.hashCode() : 0);
result = prime * result + (isOpen ? 0 : 1);
return result;
}
我相信這是重寫hashCode()
的最佳解釋。
這個答案由dmeister發布,用於以下帖子: SO:Hash Code實現 。
我一直引用它,看起來在為給定類生成hashCode()
方法時,在Eclipse中使用了這個函數。
對於幾乎所有情況,在Josh Bloch的第8項“有效Java”中提出了合理的良好實現。最好的方法是在那里查找,因為作者解釋了為什么這種方法是好的。
簡短版本:
創建一個int結果並指定一個非零值。
對於在equals-Method中測試的每個字段,通過以下方式計算哈希碼c:
- 如果字段f是布爾值:calculate
(f ? 0 : 1)
;- 如果字段f是字節,char,short或int:calculate
(int)f
;- 如果字段f是long:calculate
(int)(f ^ (f >>> 32))
;- 如果字段f是float:計算
Float.floatToIntBits(f)
;- 如果字段f是double:計算
Double.doubleToLongBits(f)
並像每個long值一樣處理返回值;- 如果字段f是一個對象:使用
hashCode()
方法的結果,如果f == null
,則使用0
;- 如果字段f是一個數組:將每個字段視為單獨的元素,並以遞歸方式計算哈希值,並按下所述組合這些值。
將哈希值c與結果結合使用:
result = 37 * result + c
返回結果
這應該導致大多數使用情況的哈希值的適當分布。
即使我為school1和school2實例設置了相同的id和名稱,但school1.equals(school2)返回false,為什么?
您需要在School類中使用equals()
方法。 否則是Object類的默認方法實現。
看默認實現
public boolean More ...equals(Object obj) {
return (this == obj);
}
在您的情況下,它是false
,因為您正在創建兩個對象。 有道理 ??
對於解決方案更喜歡閱讀 。
想象一下雙胞胎(在現實生活中),即使它們具有相同的外觀和相同的年齡和相同的名字,它們是否相等? 不,他們不是,他們是兩個不同的“實例”。
在Java中也是如此。 兩個不同的實例不能(隱含地)相等,因為它們各自在它們的存儲器中獨立存在。
但是,如果你想比較它們,你可以使用equals()方法,或者你可以創建自己的新方法進行比較。
您必須有意義地重寫equals()
方法。 從Object
類繼承的默認equals()
方法檢查兩個引用是否在內存中引用相同的對象。
類Object的equals方法實現了對象上最具辨別力的等價關系; 也就是說,對於任何非空引用值x和y,當且僅當x和y引用同一對象時,此方法才返回true(x == y的值為true)。
您已創建了2個新對象。 現在您要比較2個對象引用...您不是在比較字段成員值。所以比較是錯誤的。
對於原始數據類型,您不會遇到此問題。
如果不重寫public boolean equals(Object)方法,將調用Object.class中的版本:
public boolean equals(Object obj) {
return (this == obj);
}
只需比較引用(如果它們是完全相同的對象)!
因此,您必須在School.class中實現自己的equals(Object)。 比較這些字段:
private String name; // use String.equals(String)
private int id; // use ==
private boolean isOpen; // use ==
默認情況下,.equals()執行“==”即。,comapring引用。 你必須重寫equals()。
簡單的答案是,隱式超類Object的 equals用於比較。
從文檔:
類Object的equals方法實現了對象上最具辨別力的等價關系; 也就是說,對於任何非空引用值x和y,當且僅當x和y引用同一對象時,此方法才返回true(x == y的值為true)。 等於方法
您必須覆蓋Student類中的equals和hashcode方法。
如果不重寫equals(),那么將調用Java.lang.Object中的默認equals():
public boolean equals(Object obj) {
return (this == obj);
}
如您所見,它比較了兩個對象的引用,因此在您的情況下它返回false。
如果要比較兩個對象的內容,可以:
@Override
public boolean equals(Object obj) {
// A simple impl. Pls add some checking for null/class type/.. yourself
return this.name.equals(obj.getName()) && this.id == obj.getId() && this.isOpen == isOpen();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.