Java确定方法如何在运行时调用多态?

时间:2015-09-20 11:36:15

标签: java jvm polymorphism bytecode

虽然多态性的主要原则是脱钩"来自谁"在types方面,但让我感到困惑的是方法调用机制如何找出并在多态中调用正确的方法体。

因为在java中所有方法绑定都是late-binding,除非方法是staticfinalprivate,并且后期绑定是由JVM完成的,它预先计算{{1}对于每个类,然后在正常方法调用的运行时期间查找表。

但是在多态性过程中也会发生同样的事情。例如

假设我使用method table方法的通用课Cycle

ride()

我有三个专门课程class Cycle { public void ride(){ System.out.println("I'm Riding generic Cycle()"); } } BicycleTricycle,它扩展了通用课程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

1 个答案:

答案 0 :(得分:0)

我认为@JBNizet已经在评论中找到了解决方案(我的猜测结果证明是错误的)。但由于他没有将其作为答案发布,我会这样做:

main方法不应该显示任何动态行为,因为它始终会调用一个 方法TestRide.ride(Cycle c) 。没有其他可能的方法,所以无需弄清楚。

动态方法调用位于该方法TestRide.ride(Cycle c)内。现在您发布了该代码,确实我们看到了使用invokevirtual的动态方法调度。所以,毕竟没有惊喜。动态方法调度就在那里。