1
  class Deneme{
    public static void main(String[] args) {

       Object circle1 = new Circle();
       Object circle2 = new Circle();
       System.out.println(circle1.equals(circle2));

    }
 }

  class Circle{
       double radius;

    public boolean equals(Circle circle) {
    return this.radius == circle.radius;
    }
 }

And

  class Deneme{
     public static void main(String[] args) {

       Object circle1 = new Circle();
       Object circle2 = new Circle();
       System.out.println(circle1.equals(circle2));

      }
 }

  class Circle{
     double radius;
       @Override
       public boolean equals(Object circle) {
         return this.radius == ((Circle)circle).radius;
      }
  }

I am having issues with those codes. I have two questions. Firstly, In the first example I know equals() is not overridden. In the main method I created circle1 and circle2 objects whose declared types are Objects. And then we invoke equals() method but equals() method only take parameters whose declared types are Circle. How can it be possible? The code is running without any problems.

Secondly when i tried to run the codes i got "false" for the first example and "true" for the second in the console. Can you explain the logic behind those codes? What are we trying to prove here? What has changed when i changed the signature of equals() method from Circle circle to Object circle?

challenGer
  • 13
  • 3
  • 1
    FYI - by convention you should always start class names with uppercase and use @Override annotation https://stackoverflow.com/questions/94361/when-do-you-use-javas-override-annotation-and-why You would normally override if subclassing or doing something with default methods of Object https://www.geeksforgeeks.org/overriding-equals-method-in-java/ – JGFMK Feb 29 '20 at 16:57
  • You have to pass an Object and check it's type and whether it's `this` in the Circle class itself. Joshua Bloch, book Effective Java is good resource for this. – JGFMK Feb 29 '20 at 17:02
  • Also when you define circle1 and circle2 - they are Object - why not define them a Circle too? – JGFMK Feb 29 '20 at 17:07
  • You also need to understand the difference between overriding and overloading! You override when the method signatures are the same (parameters and returned value) - because you don't have same inbound parameter type - what you are doing is overloading the method signature. – JGFMK Feb 29 '20 at 17:15
  • Thanks i edited. Actually I know difference between overriding and overloading. This example from a java book by Y. Daniel Liang. i hadn't understood why the first example typed "false" on console. And now i know why. – challenGer Feb 29 '20 at 17:28
  • @user85421 - cheers for correction. – JGFMK Feb 29 '20 at 19:38

3 Answers3

1

The first one is not even invoking your method because you are passing Object type as reference which doesn't match you method signature and is using Object's equals instead.

You could try this to understand:

class Circle{
    double radius;

    public boolean equals(Circle circle) {
        System.out.println("This is not getting invoked");
        return this.radius == circle.radius;
    }
}
Dhrubajyoti Gogoi
  • 1,046
  • 7
  • 13
  • @WJS questions are supposed to have answers. Post the code in a comment and I take your bait. Frankly thought there is a thin line between posting a comment or filing an answer. I think it was above my threshold to put an example as an answer – Dhrubajyoti Gogoi Feb 29 '20 at 17:07
  • equals needs Object passed to it - this is probably why others downvoted you! (Not me BTW!) – JGFMK Feb 29 '20 at 17:10
  • Because when you check for equality you should also be checking it's an `instanceof Circle` as well as for `this` – JGFMK Feb 29 '20 at 17:12
  • Yes, I read that. This was just to answer why OP's code doesn't work. Agree on all best practices – Dhrubajyoti Gogoi Feb 29 '20 at 17:13
  • Thank you for your answer @DhrubajyotiGogoi. – challenGer Feb 29 '20 at 17:18
1

in the first example, you overloaded the method, for overriding, you must save the original signature of the equals method, like in the second example.

ILisa
  • 11
  • 1
1

When overriding equals try the following. It is necessary to check for null values and improper types to prevent NPE's and casting exceptions.

  class Circle{
     double radius;

       @Override
       public int hashCode() {
           return Double.valueOf(radius).hashCode();
       }

       @Override
       public boolean equals(Object obj) {
           if (obj == this) {
               return true;
           }
           if (obj instanceof Circle) {
               Circle circle =  (Circle)obj;
               return this.radius == circle.radius;
           }
           return false;
      }
  }

The main point to remember is that the type of the equals method is Object, not your class type.

WJS
  • 22,083
  • 3
  • 14
  • 32
  • Now add the @Override too! – JGFMK Feb 29 '20 at 17:19
  • You also *must* override `hashCode` if you override equals. – Andy Turner Feb 29 '20 at 18:08
  • @user85421 it would break the symmetry if a subclass of `Circle` were to override `equals` to change the semantics. `instanceof` is the right choice. http://errorprone.info/bugpattern/EqualsGetClass – Andy Turner Feb 29 '20 at 18:11
  • HashCode fixed. Thanks! Regardless of whether or not to use `instanceof` in equals, the powers that be up to Java 13 still use it even for non-final classes. Perhaps it would break existing implementations if they changed it. And the JavaDoc for hashCode says *generally you should override it* which does not sound like a mandate. – WJS Feb 29 '20 at 18:30