为什么这两个简单的对象不相等?

时间:2014-03-26 10:39:39

标签: java

我有一堂课:

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设置为school1& school2个实例,但school1.equals(school2)返回false,为什么?

9 个答案:

答案 0 :(得分:5)

您必须覆盖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 implementation

我一直引用它,看起来在为给定类生成hashCode()方法时,在Eclipse中使用了这个函数。

  

对于几乎所有情况,A提出了合理的良好实施   Josh Bloch在第8项中的“有效Java”。最好的方法就是看它   因为作者解释了为什么这种方法很好。

     

简短版本:

     
      
  1. 创建一个int结果并指定一个非零值。

  2.   
  3. 对于在equals-Method中测试的每个字段,通过以下方式计算哈希码c:

         
        
    • 如果字段f是布尔值:计算(f ? 0 : 1);
    •   
    • 如果字段f是字节,char,short或int:计算(int)f;
    •   
    • 如果字段f为long:计算(int)(f ^ (f >>> 32));
    •   
    • 如果字段f是浮点数:计算Float.floatToIntBits(f);
    •   
    • 如果字段f是double:计算Double.doubleToLongBits(f)并像每个long值一样处理返回值;
    •   
    • 如果字段f是对象:使用hashCode()方法的结果或0 f == null;
    •   
    • 如果字段f是数组:将每个字段视为单独的元素和   以递归方式计算哈希值并组合这些值   如下所述。

    •   
  4.   
  5. 将哈希值c与结果合并为:

         

    result = 37 * result + c

  6.   
  7. 返回结果

         

    这应该可以在大多数使用情况下正确分配哈希值。

  8.   

答案 1 :(得分:2)

  

即使我将相同的ID和名称设置为school1& school2实例,但school1.equals(school2)返回false,为什么?

您需要在学校课程中使用equals()方法。否则是Object类的默认方法实现。

参见默认实施

public boolean More ...equals(Object obj) {
        return (this == obj);
    }

在您的情况下,它是false,因为您正在创建两个对象。有意义吗??

对于解决方案 Prefer to read

答案 2 :(得分:2)

想象一下双胞胎(在现实生活中),即使他们有相同的外表和相同的年龄和同名,他们是否相同?不,他们不是,他们是两个不同的“实例”。

在Java中也是如此。两个不同的实例不能(隐含地)相等,因为它们各自在它们的存储器中独立存在。

但是如果你想比较它们,你可以使用equals()方法,或者你可以创建自己的新方法进行比较。

答案 3 :(得分:1)

您必须有意义地覆盖equals()方法。从Object类继承的默认equals()方法检查两个引用是否在内存中引用相同的对象。

  

类Object的equals方法实现最具辨别力   对象可能的等价关系;也就是说,对于任何非null   引用值x和y,当且仅当x时,此方法返回true   和y引用相同的对象(x == y的值为true)。

答案 4 :(得分:1)

您已创建了2个新对象。现在您要比较2个对象引用...您没有比较字段成员值。所以比较是错误的。

对于原始数据类型,您不会遇到此问题。

答案 5 :(得分:1)

如果不覆盖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 ==

答案 6 :(得分:0)

默认情况下,.equals()执行“==”即。,comapring引用。你必须覆盖equals()。

答案 7 :(得分:0)

简单的答案是,隐式超类对象的等于用于比较。

来自文档:

  

类Object的equals方法实现了对象上最具辨别力的等价关系;也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象时,此方法才返回true(x == y的值为true)。   Equals method

您必须覆盖Student类中的equals和hashcode方法。

答案 8 :(得分:0)

如果不覆盖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();
}