【问题标题】:What would happen internally when "Fish f = new BlueFish();"?当“Fish f = new BlueFish();”时内部会发生什么?
【发布时间】: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 }

问题

  1. 从程序集中创建了一个 BlueFish 对象。但是为什么javac 没有意识到应该调用BlueFish.speak()

  2. 在运行时,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


【解决方案1】:

答案:

  1. javac 不会尝试实现它,因为它很容易造成 javac 无法轻易发现甚至根本无法发现的情况。例如,您可能会通过用户输入来确定是使用CatFish 还是BlueFish

  2. 对此,请参阅 BevynQ 的评论。我很惊讶他没有将其添加为答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-13
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 2015-09-14
    相关资源
    最近更新 更多