-1

As i am learning java I found that if instances of my class are comparable i should override equals() (defined in class Object) method to determine whether two objects of my class are meaningfully equal.Probaby an attribute of the instance can be used to compare.
For a leagal override parameter passed to equals() method must be of type Object. for example.

class Moof {
      private int moofValue;
      Moof(int val) {
        moofValue = val;
      }

      public int getMoofValue() {
        return moofValue;
      }

      public boolean equals(Object o) {      // Line-1
        if ((o instanceof Moof) && (((Moof)o).getMoofValue()
             == this.moofValue)) {
          return true;
        } else {
           return false;
        }
      }

i was calling it like

        Moof one = new Moof(8);
        Moof two = new Moof(8);
        if (one.equals(two)) {
          System.out.println("one and two are equal");
        }

At Line-1 if i use public boolean equals(Moof o) it will no longer be an overriden method & becomes an overloaded method. But would it change any intended functionality? Why it is recommended to use Object as a parameter in equals would there be any harm in using the class itself whose object is being compared?
One reason i could think is if someone calls it like one.equals((Object)two)) it would call Object's equals method instead of our equals. But why would someone call it like this?

  • 2
    Probably nobody would call it like this on a variable of type `Moof`. But lots of library code internally calls it on `Object`s where it does not know the type. For examplle, if you put `one` and `two` into a `java.util.HashSet` it will call `equals` and `hashCode` internally to determine if the set has 1 or 2 members. – mihi Dec 29 '15 at 20:23
  • "Why it is recommended to use Object as a parameter in equals". You can compare anything to anything else. You can compare that a car is equals to a ship and the result will be false. You can compare an integer to a string and the result MUST be false. – Lakatos Gyula Dec 29 '15 at 20:23
  • The reason doesn't have anything to do with using an `Object` as the _parameter_, as in `one.equals((Object)two)`; rather, the problem comes up when `one` is the `Object`. Now it must call a method that overrides `Object`'s `equals`. If your `equals` method overloads but does not override, it won't get called. – ajb Dec 29 '15 at 21:31

1 Answers1

2

All the collections will call it like this. Suppose you have a list of Moofs. The list is a generic class. It doesn't even know about the types of the objects it stores. So if you try to test whether a moof is contained in the list, you'll call

list.contains(moof)

And the list will call moof.equals(theObjectStoredAtIndex0), moof.equals(theObjectStoredAtIndex1), etc. until it finds one that is equal. The only thing that the list knows about theObjectStoredAtIndex0is that it is of type Object. So it needs equals() to take an Object as argument.

Even you might do it. Suppose Moof implements Baz, and Maaf also implements Baz. And suppose you want to test if baz1 is equal to baz2. You'll do

if (baz1.equals(baz2))

The compiler has no idea of the concrete type of baz1 and baz2. All it knows is that they are both instances of Object, and thus calls, polymorphically, the Moof.equals(Object) method.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • As correct as this is...this really doesn't answer the question. This isn't asking about collections or anything like that...it's asking why it can't use the actual object that one wants to compare equals against in the signature instead of `Object`. – Makoto Dec 29 '15 at 20:24
  • And the answer explains it: the List class doesn't know the type of the objects it contains, and it needs to call equals() and pass the objects it contains as argument. So it needs `equals()` to take an Object as argument. That answers the question "why would someone call it like this?", doesn't it? – JB Nizet Dec 29 '15 at 20:28