使用.equals()和==运算符比较两个对象

91

我创建了一个只有一个 String 字段的类。然后我创建了两个对象,我需要使用 == 操作符和 .equals() 方法来比较它们。以下是我的代码:

public class MyClass {

    String a;

    public MyClass(String ab) {
        a = ab;
    }

    public boolean equals(Object object2) {
        if(a == object2) { 
            return true;
        }
        else return false;
    }

    public boolean equals2(Object object2) {
        if(a.equals(object2)) {
            return true;
        }
        else return false;
    }



    public static void main(String[] args) {

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        object1.equals(object2);
        System.out.println(object1.equals(object2));

        object1.equals2(object2);
        System.out.println(object1.equals2(object2));
    }


}

编译后,它显示两次false作为结果。如果两个对象具有相同的字段“test”,为什么会是假的?


8
顺便提一句,关于 equalsequals2 :任何时候你遇到这种形式的代码:if(a){ return true; } else { return false; },你应该直接写成 return a - yshavit
@yshavit 你的意思是将布尔值改为字符串吗? - Fastkowy
4
不,你的代码正在询问布尔值是否为真,并在其为真时返回 true,否则返回 false。例如,if(a.equals(object2)) { return true; } else return false 可以简化为 return a.equals(object2) - yshavit
1
可能是重复的问题:如何在Java中比较字符串? - bjb568
16个回答

156

== 比较的是对象引用,它检查两个操作数是否指向同一个对象(不是等价的对象,而是相同的对象)。

如果您想比较字符串(以查看它们是否包含相同的字符),则需要使用 equals 函数来比较字符串。

在您的情况下,如果两个 MyClass 实例仅在字符串匹配时才被认为是相等的,则:

public boolean equals(Object object2) {
    return object2 instanceof MyClass && a.equals(((MyClass)object2).a);
}

一般而言,如果您正在定义一个类,通常不仅要考虑单个字段 a 的等效性。


顺便提一下:如果您重写了 equals 方法,几乎总是需要重写 hashCode 方法。正如在equals 的 JavaDoc 中所述:

请注意,每当重写该方法时,通常有必要重写 hashCode 方法,以便维护 hashCode 方法的一般合同,该合同规定相等的对象必须具有相等的哈希码。


@TJ In == 比较对象引用,具体来说,它是否意味着 == 比较两个对象的哈希码? - Narendra Jaggi
@NarendraJaggi - 不,这意味着JVM检查两个操作数是否都引用同一个对象。 如何做到这一点取决于JVM,但没有理由认为它会使用哈希码来实现。 - T.J. Crowder

22

你应该重写equals方法

 public boolean equals (Object obj) {
     if (this==obj) return true;
     if (this == null) return false;
     if (this.getClass() != obj.getClass()) return false;
     // Class name is Employ & have lastname
     Employe emp = (Employee) obj ;
     return this.lastname.equals(emp.getlastname());
 }

2
这可能是最好的答案,但对于非原始类型,您可能希望使用this.equals(obj)而不是(this == null)。 - goonerify
11
我认为if (this == null)这种情况是不必要的;调用nullObject.equals(whatever)将抛出空指针异常,因此我们可以安全地假定在任何我们可能编写的Java方法中,this都不会为空。 - Maura
我认为 if (this == null) 不是不必要的,而是检查错误的对象。在第三行之前,我们需要检查 obj,所以第二个 if 应该是 if (obj == null) - Zarremgregarrok
@goonerify 这会导致StackOverflowException,因为它会递归调用相同的equals方法而没有任何停止条件。 - M. Justin
this == null 总是为假,因为 this 是指当前对象的引用 —— 而当前对象永远不可能为空! - M. Justin

7

比较两个对象的最佳方法是将它们转换为JSON字符串并进行比较。如果处理复杂的嵌套对象、字段和/或包含数组的对象,这是最简便的解决方案。

示例:

import com.google.gson.Gson;


Object a = // ...;
Object b = //...;
String objectString1 = new Gson().toJson(a);
String objectString2 = new Gson().toJson(b); 

if(objectString1.equals(objectString2)){
    //do this
}

11
我会称之为:过度杀伤。 - Rolf ツ
@Rolfツ 你为什么认为这是过度设计?我已经寻找了解决这个问题的方法,但这是我目前找到的最简单的解决方案。如果有更好的建议,欢迎提供。 - m5seppal
4
由于Java可以在不先创建Gson对象并调用toJson的情况下比较对象,因此创建Gson对象并调用将实际对象转换为平面StringtoJson)所需的逻辑是不必要的开销。你可以在不首先将对象转换为Json字符串(这也更快速)的情况下比较对象。 - Rolf ツ

6

覆盖函数equals()是错误的。 对象"a"是String类的一个实例,而"object2"是MyClass类的一个实例。它们是不同的类,所以答案是"false"。


6

看起来 equals2 只是调用了 equals,因此它会给出相同的结果。


1
OP 正在调用类成员 String aequals 方法。equals2 没有调用 equals - Yigit Alparslan
1
是的,谢谢。看起来我完全忽略了MyClass和String之间的混淆,这才是真正的问题。 - Hew Wolff
更具体地说,equals2() 比较的是 a(一个字符串)和 object2(一个对象),可能是 MyClass,在正常情况下总是返回 false。 - Zarremgregarrok

4

你的equals2()方法总是会返回与equals()相同的结果!!

带有我的注释的代码:

public boolean equals2(Object object2) {  // equals2 method
    if(a.equals(object2)) { // if equals() method returns true
        return true; // return true
    }
    else return false; // if equals() method returns false, also return false
}

6
只需返回 a.equals(object2); - mojuba

3
"

“==”运算符仅在两个引用指向同一内存对象时返回true。而equals()方法基于对象的内容返回true。

例如:

"
String personalLoan = new String("cheap personal loans");
String homeLoan = new String("cheap personal loans");

//since two strings are different object result should be false
boolean result = personalLoan == homeLoan;
System.out.println("Comparing two strings with == operator: " + result);

//since strings contains same content , equals() should return true
result = personalLoan.equals(homeLoan);
System.out.println("Comparing two Strings with same content using equals method: " + result);

homeLoan = personalLoan;
//since both homeLoan and personalLoan reference variable are pointing to same object
//"==" should return true
result = (personalLoan == homeLoan);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);

输出结果: 使用“==”运算符比较两个字符串:false 使用equals方法比较具有相同内容的两个字符串:true 使用“==”运算符比较指向相同字符串的两个引用:true

你也可以从链接中获取更多详细信息:http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1


2
如果您不需要自定义默认的toString()函数,另一种方法是覆盖toString()方法,该方法返回要比较的所有属性。然后比较两个对象的toString()输出。我使用IntelliJ IDEA IDE生成了toString()方法,其中包括类名在字符串中。
public class Greeting {
private String greeting;

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    return this.toString().equals(obj.toString());
}

@Override
public String toString() {
    return "Greeting{" +
            "greeting='" + greeting + '\'' +
            '}';
}
}

2

你的类可以实现Comparable接口来实现相同的功能。你的类应该实现在接口中声明的compareTo()方法。

public class MyClass implements Comparable<MyClass>{

    String a;

    public MyClass(String ab){
        a = ab;
    }

    // returns an int not a boolean
    public int compareTo(MyClass someMyClass){ 

        /* The String class implements a compareTo method, returning a 0 
           if the two strings are identical, instead of a boolean.
           Since 'a' is a string, it has the compareTo method which we call
           in MyClass's compareTo method.
        */

        return this.a.compareTo(someMyClass.a);

    }

    public static void main(String[] args){

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        if(object1.compareTo(object2) == 0){
            System.out.println("true");
        }
        else{
            System.out.println("false");
        }
    }
}

2
你的实现必须像这样:

您的实现必须如下所示:

public boolean equals2(Object object2) {
    if(a.equals(object2.a)) {
        return true;
    }
    else return false;
}

使用这种实现方式,你的两种方法都会起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接