虽然多态性的主要原则是在类型方面将“什么与谁”分离,但令我困惑的是方法调用机制如何找出并在多态中调用正确的方法体.
因为在java中,所有方法绑定都是后期绑定,除非该方法是静态的,最终的或私有的,并且后期绑定由JVM完成,JVM预先计算每个类的方法表,然后在运行时在正常方法调用中查找表.
但同样的事情也发生在多态性中.例如
假设我有一个带有ride()方法的Generic class Cycle
class Cycle {
public void ride(){
System.out.println("I'm Riding generic Cycle()");
}
}
我有三个Specialized Class Bicycle Tricycle和Unicycle,它扩展了Generic class 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."
":()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
."":()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."":()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."":()V
43: astore 4
45: aload 4
47: invokestatic #25 // Method ride:(Lcom/polymorphism/
Cycle;)V
50: return
即使在字节码中,它就像通常的方法一样调用invokestatic和invokespecial,而我认为它会使用invokedynamic来找出适合于对象实际类型的方法版本.但事实并非如此.
那么Java如何在多态性中找出实际的方法调用,而我们只是在testRide类中的ride()方法中传递一个上升的对象?
编辑:RIDE方法ByteCode
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