虽然多态性的主要原则是脱钩"来自谁"在types
方面,但让我感到困惑的是方法调用机制如何找出并在多态中调用正确的方法体。
因为在java中所有方法绑定都是late-binding
,除非方法是static
,final
或private
,并且后期绑定是由JVM完成的,它预先计算{{1}对于每个类,然后在正常方法调用的运行时期间查找表。
但是在多态性过程中也会发生同样的事情。例如
假设我使用method table
方法的通用课Cycle
ride()
我有三个专门课程class Cycle {
public void ride(){
System.out.println("I'm Riding generic Cycle()");
}
}
Bicycle
和Tricycle
,它扩展了通用课程Unicycle
并覆盖了其Cycle
方法。
ride()
这是测试上述多态性的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 ");
}
}
类。
TestRide
输出
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);
}
}
字节代码:
I'm Riding generic Cycle()
I'm riding Bicycle
I'm riding Tricycle
I'm Riding Unicycle
即使在字节码中,它也像往常一样调用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
和invokestatic
,而我认为它会使用invokespecial
来确定适合实际的方法的版本对象的类型。但事实并非如此。
那么Java如何在多态性中找出实际的方法调用,而我们只是在invokedynamic
方法中传递一个上升的对象,如ride()
类中的ride(bi)
?
编辑:RIDE方法ByteCode
TestRide
答案 0 :(得分:0)
我认为@JBNizet已经在评论中找到了解决方案(我的猜测结果证明是错误的)。但由于他没有将其作为答案发布,我会这样做:
main
方法不应该显示任何动态行为,因为它始终会调用一个 单方法TestRide.ride(Cycle c)
。没有其他可能的方法,所以无需弄清楚。
动态方法调用位于该方法TestRide.ride(Cycle c)
内。现在您发布了该代码,确实我们看到了使用invokevirtual
的动态方法调度。所以,毕竟没有惊喜。动态方法调度就在那里。