How do Java methods define methods at run time in polymorphism?

While the basic principle of polymorphism unleashes “which of whom” in terms of types , but what confuses me is how it clarifies the method invocation method and invokes the correct method body in polymorphism.

Since in java the whole binding of the late-binding method is if the method is not static , final or private , and the late binding is done by the JVM, which pre-computes the method table for each class and then makes a table at runtime during a normal call to the call.

But the same thing happens with polymorphism. for instance

Suppose I have a common Cycle class with the ride() method

 class Cycle { public void ride(){ System.out.println("I'm Riding generic Cycle()"); } } 

And I have three specialized classes, Bicycle Tricycle and Unicycle , which extend the general Cycle class and override its ride() method.

 class Bicycle extends Cycle { public void ride() { System.out.println("I'm riding Bicycle"); } } class Tricycle extends Cycle{ public void ride() { System.out.println("I'm riding Tricycle "); } } class Unicycle extends Cycle { public void ride() { System.out.println("I'm Riding Unicycle "); } } 

This is the TestRide class to test the above polymorphism.

 public class TestRide { public static void ride(Cycle c){ c.ride(); } public static void main(String[] args){ Cycle Cycling = new Cycle(); ride(Cycling); Bicycle bi = new Bicycle(); ride(bi); Tricycle tri = new Tricycle(); ride(tri); Unicycle uni = new Unicycle(); ride(uni); } } 

Output

 I'm Riding generic Cycle() I'm riding Bicycle I'm riding Tricycle I'm Riding Unicycle 

Bytecode:

 public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=5, args_size=1 0: new #17 // class com/polymorphism/Cycle 3: dup 4: invokespecial #24 // Method com/polymorphism/Cycle." <init>":()V 7: astore_1 8: aload_1 9: invokestatic #25 // Method ride:(Lcom/polymorphism/ Cycle;)V 12: new #27 // class com/polymorphism/Bicycle 15: dup 16: invokespecial #29 // Method com/polymorphism/Bicycle ."<init>":()V 19: astore_2 20: aload_2 21: invokestatic #25 // Method ride:(Lcom/polymorphism/ Cycle;)V 24: new #30 // class com/polymorphism/Tricycle 27: dup 28: invokespecial #32 // Method com/polymorphism/Tricycl e."<init>":()V 31: astore_3 32: aload_3 33: invokestatic #25 // Method ride:(Lcom/polymorphism/ Cycle;)V 36: new #33 // class com/polymorphism/Unicycle 39: dup 40: invokespecial #35 // Method com/polymorphism/Unicycl e."<init>":()V 43: astore 4 45: aload 4 47: invokestatic #25 // Method ride:(Lcom/polymorphism/ Cycle;)V 50: return 

Even in the byte encoder, as usual, a call is invoked with invokestatic and invokespecial , while I thought that it would use invokedynamic to determine the version of the method suitable for the actual type of the object. But that was not so.

So, how does Java compute the actual method call during polymorphism, while we just pass the object up in the ride() method, like ride(bi) in the TestRide class?

EDIT: RIDE ByteCode Method

 public static void ride(com.polymorphism.Cycle); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokevirtual #16 // Method com/polymorphism/Cycle.r ide:()V 4: return 
+5
source share
2 answers

invokedynamic intended for Java 8 lambdas and non-Java code first, so you can forget about it.

In addition, there are four calling commands ( invokespecial , invokestatic , invokevirtual and invokeinterface ). You can see the exact semantics in the JVM sepcification, but the bottom line indicates that invokevirtual and invokeinterface are virtual method calls, i.e. the actual method invokeinterface is selected at runtime based on the type of target connection.

The only virtual call in your code is in TestRide.ride. The indicated target is Cycle.ride:()V However, since this is a virtual call, the JVM checks the actual type of the first argument at run time and calls the most derived version of this method.

This is similar to invoking virtual methods in C ++, except that the abstraction of JVM and JIT compilation allows the use of more optimized implementations.

Also note that this should not 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 type of compilation time of the arguments.

+1
source

I think @JBNizet figured out the solution already in the comments (and my hunch turned out to be wrong). But since he does not send it as an answer, I will do this:

The main method should not show dynamic behavior, because it will always call this single method TestRide.ride(Cycle c) . There is no other possible method, so do not understand anything.

A dynamic method call is inside this TestRide.ride(Cycle c) method. And now that you have posted this code, indeed, we see a dynamic submit method using invokevirtual . So, in the end, no surprises. Sending a dynamic method is.

0
source

All Articles