91

I constructed a class with one String field. Then I created two objects and I have to compare them using == operator and .equals() too. Here's what I've done:

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));
    }


}

After compile it shows two times false as a result. Why is it false if the two objects have the same fields - "test"?

Hash
  • 4,647
  • 5
  • 21
  • 39
Fastkowy
  • 1,285
  • 3
  • 15
  • 16
  • 8
    Btw, looking at `equals` and `equals2`: any time you have something of the form `if(a) { return true; } else { return false; }` you should probably just write `return a`. – yshavit Nov 14 '12 at 21:44
  • @yshavit You mean, with change from boolean to String? – Fastkowy Nov 14 '12 at 21:53
  • 4
    no, your code is asking if a boolean is a true, and returning `true` if it is and `false` otherwise. So for instance, `if(a.equals(object2)) { return true; } else return false` could just be `return a.equals(object2)`. – yshavit Nov 14 '12 at 21:57
  • 1
    possible duplicate of [How do I compare strings in Java?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – bjb568 Apr 04 '15 at 00:52

16 Answers16

156

== compares object references, it checks to see if the two operands point to the same object (not equivalent objects, the same object).

If you want to compare strings (to see if they contain the same characters), you need to compare the strings using equals.

In your case, if two instances of MyClass really are considered equal if the strings match, then:

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

...but usually if you are defining a class, there's more to equivalency than the equivalency of a single field (a in this case).


Side note: If you override equals, you almost always need to override hashCode. As it says in the equals JavaDoc:

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @TJ In == compares object references, to elaborate, Does it mean == compares hashcode of the two objects? – Narendra Jaggi May 07 '20 at 13:39
  • @NarendraJaggi - No, it means that the JVM checks to see if the two operands both refer to the same object. *How* it does that is up to the JVM, but there's no reason to think it would use a hashcode to do it. – T.J. Crowder May 07 '20 at 15:06
22

You should override 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());
 }
darclander
  • 1,526
  • 1
  • 13
  • 35
user5119219
  • 245
  • 2
  • 2
  • 2
    This is arguably the best answer, however you might want to use this.equals(obj) instead of (this == null) for non primitive types – goonerify Nov 25 '15 at 05:18
  • 11
    I'd argue that the `if (this == null)` case is unnecessary anyway; calling `nullObject.equals(whatever)` is going to throw a null pointer exception, so we can safely assume that `this` is not null in any Java method we may write. – Maura Oct 03 '16 at 21:42
  • I'd argue that `if (this == null)` is not unnecessary, but wrong object checked. Before the third line we need `obj` checked so the second if should be `if (obj == null)` – Zarremgregarrok Jan 19 '21 at 10:13
  • @goonerify That would lead to a `StackOverflowException`, as it would recursively call the same `equals` method without any stop condition. – M. Justin May 27 '21 at 05:59
  • `this == null` will always be false, since `this` is a reference to the current object — which can never be null! – M. Justin May 27 '21 at 06:00
7

The best way to compare 2 objects is by converting them into json strings and compare the strings, its the easiest solution when dealing with complicated nested objects, fields and/or objects that contain arrays.

sample:

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
}
JoeG
  • 182
  • 1
  • 3
  • 11
    I would like to call this: overkill. – Rolf ツ Jan 02 '17 at 15:40
  • @Rolfツ Why this is overkill in your opinion? I've looked for a solution to this problem and this is the easiest solution I've found so far. Any better suggestions are welcome. – m5seppal Dec 20 '17 at 13:09
  • 4
    Because with Java you can compare objects without first creating a `Gson` object and then calling `toJson`. Creating the `Gson` object and calling the logic needed to convert the actually object to a flat `String` (`toJson`) is unnecessary overhead. You can compare objects without first converting the objects to Json strings (which is also quicker). – Rolf ツ Dec 20 '17 at 13:14
6

The overwrite function equals() is wrong. The object "a" is an instance of the String class and "object2" is an instance of the MyClass class. They are different classes, so the answer is "false".

5

It looks like equals2 is just calling equals, so it will give the same results.

Hew Wolff
  • 1,489
  • 8
  • 17
  • 1
    OP is calling the `equals` method of the String `a` which is a member of the class. `equals2` is not calling `equals` – Yigit Alparslan Nov 18 '20 at 06:58
  • 1
    Yes, thanks. Looks like I totally missed the confusion between MyClass and String which is the real problem. – Hew Wolff Nov 19 '20 at 16:54
  • to be more specific `equals2()` compares `a` which is `String` with `object2` which is `Object` and probably `MyClass` which would in normal usage always return false. – Zarremgregarrok Jan 19 '21 at 10:19
3

Your equals2() method always will return the same as equals() !!

Your code with my comments:

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
}
jlordo
  • 37,490
  • 6
  • 58
  • 83
3

The "==" operator returns true only if the two references pointing to the same object in memory. The equals() method on the other hand returns true based on the contents of the object.

Example:

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);

Output: Comparing two strings with == operator: false Comparing two Strings with same content using equals method: true Comparing two references pointing to same String with == operator: true

You can also get more details from the link: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1

Madhan
  • 555
  • 5
  • 23
2

Statements a == object2 and a.equals(object2) both will always return false because a is a string while object2 is an instance of MyClass

VMAtm
  • 27,943
  • 17
  • 79
  • 125
ashish.al
  • 21
  • 2
2

Your implementation must like:

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

With this implementation your both methods would work.

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Azhar Khan
  • 99
  • 1
  • 8
2

Your class might implement the Comparable interface to achieve the same functionality. Your class should implement the compareTo() method declared in the interface.

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");
        }
    }
}
Community
  • 1
  • 1
tf3
  • 447
  • 1
  • 4
  • 16
2

If you dont need to customize the default toString() function, another way is to override toString() method, which returns all attributes to be compared. then compare toString() output of two objects. I generated toString() method using IntelliJ IDEA IDE, which includes class name in the string.

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 + '\'' +
            '}';
}
}
Qinjie
  • 1,786
  • 2
  • 19
  • 32
1

the return type of object.equals is already boolean. there's no need to wrap it in a method with branches. so if you want to compare 2 objects simply compare them:

boolean b = objectA.equals(objectB);

b is already either true or false.

Cpt. Mirk
  • 11
  • 1
1

When we use == , the Reference of object is compared not the actual objects. We need to override equals method to compare Java Objects.

Some additional information C++ has operator over loading & Java does not provide operator over loading. Also other possibilities in java are implement Compare Interface .which defines a compareTo method.

Comparator interface is also used compare two objects

1

Here the output will be false , false beacuse in first sopln statement you are trying to compare a string type varible of Myclass type to the other MyClass type and it will allow because of both are Object type and you have used "==" oprerator which will check the reference variable value holding the actual memory not the actual contnets inside the memory . In the second sopln also it is the same as you are again calling a.equals(object2) where a is a varible inside object1 . Do let me know your findings on this .

Bidyadhar
  • 11
  • 1
  • 2
    Welcome to stackoverflow bidyadhar. The question is dated 14/11/2012 and got already a good response (approved by OP). The one that you got is correct, but it is not adding useful info. I suggest you to read the rules before doing anything – Nikaido Jul 06 '17 at 14:56
0

In short, == compares two POINTERS.

If the two pointers are equal, then they both point to same object in memory (which, obviously has the same value as itself).

However, .equals will compare the VALUES of whatever is pointed to, returning true iff they both evaluate to the same value.
Thus, two separate strings (i.e., at different addresses in memory) are always != but are .equal iff they contain the same (null-terminated) sequence of chars.

-3

IN the below code you are calling the overriden method .equals().

public boolean equals2(Object object2) { if(a.equals(object2)) { // here you are calling the overriden method, that is why you getting false 2 times. return true; } else return false; }

Ram
  • 11