In the first version you override a method and in the second method you overload it.
In the first version you have p
in both class A
and class B
. When you call c.p(...)
the compiler uses the static type of c
to create the call. On run time the code uses the class`s virtual table (read about it if you're not familiar) in order to find the correct polymorphic method.
In the second version the compiler does the cast from int to double for you on compile time and then on run-time it again uses the virtual table of A
to find a method with signature p(double)
(because it casted the int on compile-time for static-type compliance). The virtual table points to the method in B
because A
doesn't override it.
You can further read about it in the book "Effective Java" - Item 41, Page 191:
selection among overloaded methods is static, while selection among overridden methods is dynamic