簡體   English   中英

為什么這兩個簡單的對象不相等?

[英]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));

    }

即使我設置相同的idname ,以school1school2實例,但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”中提出了合理的良好實現。最好的方法是在那里查找,因為作者解釋了為什么這種方法是好的。

簡短版本:

  1. 創建一個int結果並指定一個非零值。

  2. 對於在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是一個數組:將每個字段視為單獨的元素,並以遞歸方式計算哈希值,並按下所述組合這些值。

  3. 將哈希值c與結果結合使用:

    result = 37 * result + c

  4. 返回結果

    這應該導致大多數使用情況的哈希值的適當分布。

即使我為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM