The reference variable typ
in your example is of type Object
.
The object that it refers to is of type Types
.
The compiler does not have enough information to know that the object is actually Types
and use Type.equals(Object)
.
This may be confusing. If you write
Object typ = new Types();
Then surely the compiler knows that what there is in typ
is Types
. It just compiled that information into the code!
However, what if you decide to change that line into
Object type = new ObjectFactory().choose(choice).use(decision).build();
Well, now you don't actually know what the build
will come up with. This will be known only at run time, after the ObjectFactory decides what to do with the values of choice
and decision
.
So in this case, the compiler doesn't know. The only information available to it is the static type of the variable. And it would be very bad if the compiler behaved differently when you used new
than when you used a factory like above.
Now look at this scenario:
public class Types {
public boolean equals( Object obj ) {
// something
}
public boolean equals( String str ) {
return false;
}
}
public class Main {
public static void main(String[] args) {
Object typ = new Types();
System.out.println( typ.equals("foo" ) );
}
}
Now, in this case, Types
and Main
are two separate compilation units (different files etc.). Suppose the compiler decided to go according to the fact that typ
is Types
. It would then use Types.equals(String)
.
But now you can edit Types
, remove the equals(String)
, and recompile only Types
. When you run the program, you'll get a "no such method exception", because the compiler assumed Types
has an equals(String)
method. So your program fails, despite being a perfectly legal Java program and despite having a proper, matching method equals(Object)
in the new Types
.
So the real compiler uses the static type to determine whether a method exists and is legal with the given static parameters, and only at runtime, the JVM will be able to find what the actual type is, and call the applicable override of that method.