While the main principle of polymorphism is decoupling \"what from who\" in term of types
, but what confuses me how does method-call mechanism finds out and cal
I think @JBNizet figured out the solution already in the comments (and my guess turned out to be wrong). But since he doesn't post it as an answer, I'll do it:
The main
method isn't supposed to show any dynamic behavior because it is always ever going to call that one single method TestRide.ride(Cycle c)
. There is no other possible method, so nothing to figure out.
The dynamic method call is inside that method TestRide.ride(Cycle c)
. And now that you posted that code, indeed we see a dynamic method dispatch using invokevirtual
. So, after all, no surprises. The dynamic method dispatch is there.
First off invokedynamic
is for Java 8 lambdas and non-Java code, so you can forget about that.
Apart from that, there are four invoke instructions (invokespecial
, invokestatic
, invokevirtual
, and invokeinterface
). You can see the precise semantics in the JVM sepcification, but the bottom line is that invokevirtual
and invokeinterface
are virtual method calls, i.e. the actual method called is chosen at runtime based on the conrete type of the target.
The only virtual call in your code is in TestRide.ride. The listed target is Cycle.ride:()V
. However, since it is a virtual call, the JVM will check the actual type of the first argument at runtime and call the most derived version of that method.
This is similar to virtual method calls in C++, except that the abstraction of the JVM and JIT compilation allows the potential for more optimized implementations.
Also note that this is not to be confused with method overloading, which is a form of compile-time polymorphism. For overloaded methods, the compiler chooses which one to call based on the compile time type of the arguments.