Java动态多态性与类文件

Java动态多态性与类文件,java,Java,我试图理解动态多态性是如何实现的。我有以下代码 public class Bike { void run() { System.out.println("bike is running"); } } public class Honda extends Bike{ void run() { System.out.println("honda is running"); } public static void main(String[] args) { Bike b

我试图理解动态多态性是如何实现的。我有以下代码

public class Bike {
 void run() {
   System.out.println("bike is running");
 }
}

public class Honda extends Bike{
 void run() {
   System.out.println("honda is running");
 }
 public static void main(String[] args) {
   Bike b = new Honda();
   b.run(); // output 'honda is running'
 }
}
我试图查看本田class的类文件,下面是主方法的字节码

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #1                  // class newpackage/Honda
         3: dup
         4: invokespecial #31                 // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #32                 // Method newpackage/Bike.run:()V
        12: return
publicstaticvoidmain(java.lang.String[]);
描述符:([Ljava/lang/String;)V
标志:(0x0009)ACC_公共,ACC_静态
代码:
堆栈=2,局部变量=2,参数大小=1
0:new#1//classnewpackage/本田
3:dup
4:invokespecial#31//方法“”:()V
7:astore_1
8:aload_1
9:invokevirtual#32//方法newpackage/Bike.run:()V
12:返回
第9行有invokevirtual#32,它是常量池中的第32个位置,解析为Bike.run。Bike类没有#32,其常量池只持续到#30
运行时会发生什么情况以及Honda类的run方法最终是如何被调用的?

编号的参数仅适用于特定的类文件,而不适用于跨类文件。正如您所确定的,它解析为
Bike.run
——此时,JVM转到
Bike
类并查找其名为
run
的方法>是的,这就是我试图理解的,它解析为Bike.run,所以输出应该是“Bike is running”。然而,输出是“honda is running”,这意味着调用了honda.run。在类文件中,我们可以看到Bike.run应该根据字节码“9:invokevirtual#32”调用@云这就是
invokevirtual
的意思——您正在调用
run
方法,该方法由
Bike
声明,但如果您重写子类中的一个方法,则该方法将在运行时执行。这是多态性的本质。为混淆道歉。我从概念上理解多态性。我想知道jvm在到达第9行时会执行该操作,以及该方法的解析方式。例如,在第8行,必须执行第9行之后,aload_1将在操作数堆栈中加载引用变量b,并且根据字节码,它应该调用bike类的run方法,因为该方法位于#32。jvm在内部如何调用honda cla上的run方法ss.我认为它不会在运行时更改第9行的字节码。@您似乎在询问绑定,简短的回答是它会进行某种查找,将(1)正在调用的引用变量的类型和(2)组合在一起方法签名。这是如何实现的依赖于实现,但它通常看起来像是C++ VTABLE,这可能是一个有用的参考主题。是的,我想知道JVM如何在运行时决定调用的方法。ALOADY1加载引用变量B然后执行EnvoEvrRealError。方法签名我假设它结合了这个方法签名和引用变量的类型来调用合适的方法。但是#32解析为Bike.run(#3.#33,#3是Bike,#33是run:()V)。对此有什么想法吗?我试图了解更多,但没有找到任何好的材料。