【发布时间】:2013-07-12 00:37:47
【问题描述】:
假设我们有:
1 public class DynamicDispatch {
2 public static void main(String[] args) {
3 Fish f = new BlueFish();
4 f.speak();
5 }
6 }
7
8 abstract class Fish {
9 abstract String speak();
10 }
11
12 class BlueFish extends Fish {
13 String speak() {
14 return "I am a blue fish";
15 }
16 }
17
18 class CatFish extends Fish {
19 String speak() {
20 return "I am a cat fish";
21 }
22 }
问题:
从程序集中创建了一个 BlueFish 对象。但是为什么
javac没有意识到应该调用BlueFish.speak()?在运行时,JVM 如何处理
invokespecial #4,以便调用正确的目标?
仅供参考,javap -c 输出为:
Compiled from "DynamicDispatch.java"
public class DynamicDispatch extends java.lang.Object{
public DynamicDispatch();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class BlueFish
3: dup
4: invokespecial #3; //Method BlueFish."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4; //Method Fish.speak:()Ljava/lang/String;
12: pop
13: return
}
【问题讨论】:
-
你可以编译它并查看生成的字节码...
-
对象实例有一个在运行时查找的虚拟方法表。该表是在实例化对象时构建的,因此特定于对象的类型。 Javac 不需要知道对象类型是什么,它所做的只是从表中选择方法号 4。
-
@BevynQ 你能指出一些关于 Java 虚拟方法表的参考资料吗?谢谢!
标签: java jvm javac dynamic-binding dynamic-dispatch