• Post Reply Bookmark Topic Watch Topic
  • New Topic

Object method override question  RSS feed

 
N Sam
Ranch Hand
Posts: 77
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I read the following comment at stackoverflow.com. It is not clear to me why equals in the code below does not override - i looked up Object class equals() and the signature is same.

public class Foo {
private String id;
public boolean equals(Foo f) { return id.equals(f.id);}
}
This class compiles as written, but adding the @Override tag to the equals method will cause a compilation error as it does not override the equals method on Object.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
N Sam wrote:I read the following comment at stackoverflow.com. It is not clear to me why equals in the code below does not override - i looked up Object class equals() and the signature is same.

public class Foo {
private String id;
public boolean equals(Foo f) { return id.equals(f.id);}
}
This class compiles as written, but adding the @Override tag to the equals method will cause a compilation error as it does not override the equals method on Object.



Hint: What is the difference between overriding and overloading? Specifically, regarding the method signatures?
 
N Sam
Ranch Hand
Posts: 77
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In overriding, the signature has to be the same between the 2 methods (including parameter types and position). The signature in Object class is
public boolean equals(Object obj)
The code i supplied has equals() different only in the parameter Foo f. But i thought "Foo" is an "Object" too, so it is equivalent to above signature described in the Object class.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
N Sam wrote:In overriding, the signature has to be the same between the 2 methods (including parameter types and position). The signature in Object class is
public boolean equals(Object obj)
The code i supplied has equals() different only in the parameter Foo f. But i thought "Foo" is an "Object" too, so it is equivalent to above signature described in the Object class.


So... based on your theory, the StringBuffer class, which has a method called append(Object) and a method called append(String) should fail to compile? Because a String is an Object. and hence, it is not overloading? I know that I am making a silly point, but it is very similar to yours. How are the two different?

Henry
 
N Sam
Ranch Hand
Posts: 77
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK - the parameter should match for this to override the "Object class equals()". So the correct code would be....
 
Campbell Ritchie
Marshal
Posts: 56578
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
N Sam wrote:OK - the parameter should match for this to override the "Object class equals()". So the correct code would be....
. . .
No. Not at all. That will not even compile because most Objects do not have an id field.

An overridden equals() method is one of the most difficult things to get right: I suggest you look at all these three resources:
  • 1: Joshua Bloch's Effective Java™ chapter 3
  • 2: Angelika Langer's Java equals and hashCode FAQ
  • 3: Odersky Spoon and Venners.
  • Each resource shows something slightly different, so it is worth reading all three. You must also override the hashCode method.
     
    N Sam
    Ranch Hand
    Posts: 77
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks Campbell, for the pointers. The code piece was from stackoverflow.com. From what i have read, the correct override code would be ....

    Also, the rule "always override hashcode, when equals is overridden" is on my mind.
    Did i get it right ?
     
    Winston Gutkowski
    Bartender
    Posts: 10575
    66
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    N Sam wrote:But i thought "Foo" is an "Object" too, so it is equivalent to above signature described in the Object class.

    No, that only works for return types (and only since Java 1.5; Google "covariant return types" for more info).

    The basic lesson here: Always add "@Override" when you're overriding a method.

    Also, the rule "always override hashcode, when equals is overridden" is on my mind.

    That's right. In general, those two methods should always be overridden together unless you clearly document that they aren't. And there can be reasons for breaking the rule, but it's far better to learn it and make it a habit before you do so.

    Also: Deal with one thing at a time. Make sure you read and understand how equals() works first, then tackle hashCode(); because there's a whole new set of rules to know about for that method too.

    In addition to the links given by Campbell, my advice would be to also read the rules set out in Object.equals() carefully, because they are VERY important.

    HIH

    Winston

    PS: You might also be interested in the FirstClasses page, which goes into the subject in some detail (and is also based on the links that Campbell provided), but it's fairly long.
     
    Campbell Ritchie
    Marshal
    Posts: 56578
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Winston Gutkowski wrote: . . . rules set out in Object.equals() carefully, because they are VERY important. . . .
    They are also very easy to understand, even if they look complicated.
  • 1: This is the difficult one to spot: “for any non‑null reference” … means that the method always returns true or false. It cannot therefore throw an Exception.
  • 2: Reflexive: every object is equal to itself.
  • 3: Symmetric: you get the same result if you swap the two references.
  • 4: Transitive: if x.equals(y) and y.equals(z), then x.equals(z)
  • 5: Consistent: you always get the same result.
  • 6: An object which exists is implicitly different from an object which does not exist.
  • The only way you can get an Exception from x.equals(y) is if x is null.

    Have a look at the Bloch reference I gave you earlier, and see whether he describes a canEqual method. That can deal with nulls. It is probably how this is implemented.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!