首页 > 解决方案 > 为什么 java 对象比较在 '==' 和 .equals() 方法上都失败了?

问题描述

我正在使用 == 和 equals() 方法比较相同的对象,但它们都失败了。我尝试了以下四种组合。请有人指导我在哪里犯错。

public class Question {

int rollNo;
String name;

Question(int rollNo, String name) {
    this.rollNo = new Integer(rollNo);
    this.name = new String(name);
}

public int getRollNo() {
    return new Integer(rollNo);
}

public void setRollNo(int rollNo) {
    if(rollNo>0) this.rollNo = rollNo;
}

public String getName() {
    return new String(name);
}

public void setName(String name) {
    if(name!=null) this.name = name;
}

public static void main(String[] args) {
    Question obj1 = new Question(123, "Student1");
    Question obj2 = new Question(123, "Student1");
    Question obj3 = new Question(456, "Student2");

            // All if conditions are evaluating to false
    if(obj1 == obj2) System.out.println("Equal objects 1 and 2 using ==");
    if(obj1.equals(obj2)) System.out.println("Equal objects 1 and 2 using equals()");
    if(obj1 == new Question(123, "Student1")) System.out.println("Equal objects 1 and 2 using == and new");
    if((new Question(123, "Student1")).equals(obj2)) System.out.println("Equal objects 1 and 2 using equals() and new");        
}

}

我也欢迎关于我的代码质量的建议,因为我刚刚开始编码。

标签: java

解决方案


它失败了,==因为Question对象是不同的对象。(==引用类型的运算符测试以查看引用是否针对同一对象。)

它失败了,equals因为您正在使用该Object::equals(Object)方法。该方法被指定为具有与 相同的含义==

如果你想Question::equals(Object)表现得不同,你需要通过添加这样的方法来覆盖继承自的方法:Object

    @Override
    public boolean equals(Object other) {
        // implement this according to the spec to give the equality
        // semantics you need
    }

实际的实现可能如下所示:

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof Question) {
            Question other = (Question) obj;
            return this.rollNo == other.rollNo &&
                   this.name.equals(other.name);
        } else {
            return false;
        }
    }

我注意到您的代码中还有其他一些问题。例如:

    Question(int rollNo, String name) {
        this.rollNo = new Integer(rollNo);
        this.name = new String(name);
    }
  1. 构造函数应该是public.
  2. 由于this.rollNo被声明为 an int,因此创建 anInteger并分配它是毫无意义的......而且效率低下。将会发生的情况是,Integer将拆箱以获取其值,然后该对象将被丢弃。只需分配rollNothis.rollNo.
  3. 如果您确实需要显式获取Integer实例,那么正确的方法是使用. 这利用了内置的对象缓存。Integer.valueOf(int)Integer
  4. 创建一个字符串new String(name)是不必要且低效的。字符串是不可变的。不需要复制它们。当然,不是这里。

推荐阅读