5

I have a School class:

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

Then I created two instances of School, and compare the equality of the two instances:

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

    }

Even though I set the same id and name to school1 & school2 instances, but school1.equals(school2) returns false, why?

4
  • 2
    You didn't override the equals method in your class. So you get the default behavior, i.e public boolean equals(Object obj) {return (this == obj);}. Since you're creating two brand new objects, it returns false. If you've done School school2 = school1;, it would output true.
    – Alexis C.
    Commented Mar 26, 2014 at 10:40
  • If you're using Eclipse you can generate the equals() method by doing right click on the class > Source > Generate Hashcode() and equals() Commented Mar 26, 2014 at 10:46
  • check out this question answer it may help you stackoverflow.com/questions/16069106/…
    – Swapnil
    Commented Mar 26, 2014 at 10:46
  • possible duplicate of Compare two objects with .equals() and == operator Commented Mar 26, 2014 at 10:48

9 Answers 9

5

You have to override the equals(Object) method:

Place this in your School class:

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

If you are going to this, it is also wise to override the hashCode() method as well.

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

Additional Information

I believe this is the best explanation of overriding hashCode().

This answer was posted by dmeister for the following post: SO: Hash Code implementation.

I reference this all the time, and it looks like this functionallity is used in Eclipse when generating the hashCode() method for a given class.

A for nearly all cases reasonable good implementation was proposed in Josh Bloch's "Effective Java" in item 8. The best thing is to look it up there because the author explains there why the approach is good.

A short version:

  1. Create a int result and assign a non-zero value.

  2. For every field tested in the equals-Method, calculate a hash code c by:

    • If the field f is a boolean: calculate (f ? 0 : 1);
    • If the field f is a byte, char, short or int: calculate (int)f;
    • If the field f is a long: calculate (int)(f ^ (f >>> 32));
    • If the field f is a float: calculate Float.floatToIntBits(f);
    • If the field f is a double: calculate Double.doubleToLongBits(f) and handle the return value like every long value;
    • If the field f is an object: Use the result of the hashCode() method or 0 if f == null;
    • If the field f is an array: See every field as separate element and calculate the hash value in a recursive fashion and combine the values as described next.

  3. Combine the hash value c with result with:

    result = 37 * result + c

  4. Return result

    This should result in a proper distribution of hash values for most use situations.

2
  • What about the hashCode method? Commented Mar 26, 2014 at 10:46
  • It should still be mentioned in the answer, no need to provide implementation but the person asking the question must be aware of it. Commented Mar 26, 2014 at 10:49
2

Imagine twins (in real life), even if they have same look and same age and same name, are they equal? No they are not, they are two different "instances".

It is same in Java. Two different instances cannot be (implicitly) equal, because they each exist independently in their part of memory.

However if you want to compare them like that, you can ovveride equals() method or you can create your own new method for comparing.

2

Even though I set the same id and name to school1 & school2 instances, but school1.equals(school2) returns false, why?

You need to ovveride the equals() method in your School class. Otherwise the default method implementation from Object class.

see default implementation

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

In your case it is false, since you are creating two objects. making sense ??

For solution Prefer to read.

4
  • 3
    You were so rushed to answer first, your "answer" contained several spelling mistakes. All you do now is add tiny bits until it is somewhat a decent answer. Even now, there is still not a solution present. Commented Mar 26, 2014 at 10:44
  • @JeroenVannevel overriding equals method is not a solution ? Commented Mar 26, 2014 at 10:48
  • That is the general solution but "give everybody a piece of bread" is not a solution to end world hunger either. If you're going to give an answer that basically says "here's how to approach it, now google it" then it is not an answer. Either flag it as a duplicate of the question where he'll end up after googling it or provide an answer that explains why this has to be done and what has to be done specifically. Commented Mar 26, 2014 at 10:52
  • 1
    @JeroenVannevel Well you haven't read the actual question. OP is asking why it is false. I hope I explained it a bit. Commented Mar 26, 2014 at 10:54
1

You have to override the equals() method meaningfully. The default equals() method inherited from Object class check if two reference are referring same object in the memory.

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

1

You have created 2 new objects. Now you are comparing 2 object references ... You are not comparing field member values.. So comparison is false.

For primitive datatypes, you wouldn't have this problem.

1

If you do not override the public boolean equals(Object) method, the version in Object.class will be called:

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

Just compare the references(If they are exactly the same object)!

So, you have to implement your own equals(Object) in the School.class. Compare these fields:

private String name;  // use String.equals(String)
private int id;  // use ==
private boolean isOpen; // use ==
0

By default, .equals() does "==" ie., comapring references. You have to override equals().

0

The simple answer is, equals of the implicit super class Object is being used for comparison.

From the documentation:

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true). Equals method

You would have to override the equals and hashcode method in your Student class.

0

If you don't override the equals(), then the default equals() in Java.lang.Object will be called:

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

As you see, it compares the references of two object, so in your case it returns false.

If you want to compare the contents of two object, you can:

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.