The first thing you should note is that public boolean equals(Test testje)
doesn't override Object
's equals
, since the argument is Test
instead of Object
, so the signatures don't match.
Therefore the main
method calls equals(Test testje)
exactly once - when executing t3.equals(t3);
- since that's the only case in which both the static type of the instance equals
is executed for and the type of the argument are the Test
class.
t3.equals(t3);
is the 4th equals
statement (which comes after 4 increments of the static count
variable), so 4 is printed.
All the other equals
statements execute Object
's equals
, and therefore print nothing.
A more detailed explanation :
t1.equals()
calls Object
's equals
regardless of the type of the argument, since the static (compile time) type of t1
is Object
, and the Test
class doesn't override that method. The Object
class doesn't have an equals
method with a single Test
argument, so equals(Test testje)
can't be called, regardless of the dynamic (runtime type) of t1
.
t3.equals()
can execute either Object
's equals
or Test
's equals, since the compile time type of t3
is Test
, and the Test
class has two equals
methods (one inherited from the Object
class and the other defined in the Test
class).
The method being chosen depends on the compile time type of the argument :
1. When the argument is Object
(as in t3.equals(o1);
or t3.equals(t2);
), Object
's equals
is called and nothing is printed.
2. When the argument is Test
, as in t3.equals(t3);
, both versions of equals
match that argument, but due to the rules of method overloading, the method with the most specific argument - equals(Test testje)
- is chosen and the count
variable is printed.