学习笔记 从class指令文件中理解java的多态是如何实现的

这段代码的结果是什么呢,结果出乎我以前对java的认识

public class TestClass {
    static void sayHello(P p){
        System.out.println("P");
    }
    static void sayHello(A p){
        System.out.println("A");
    }
    static void sayHello(B p){
        System.out.println("B");
    }
    public static void main(String [] args){
        P a = new A();
        P b = new B();
        sayHello(a);
        sayHello(b);
    }
    //父类
    abstract static class P{
    }
    //子类A
    static class A extends P{     
    }
    //子类B
    static class B extends P{   
    }
}

打印结果

P
P

为什么是这样的结果呢,以我的之前的认识 a 和 b 已经是 A 和 B的对象了  应该打印 A 和 B 才是

看一了下编译之后的代码 才明白

学习笔记 从class指令文件中理解java的多态是如何实现的

这行代码 在常量池定义的方法名称

学习笔记 从class指令文件中理解java的多态是如何实现的

执行到这段的时候 直接引用的是 常量池的 sayHello(P)的方法 所以上面两个sayHello执行的结果是相同的

下面看更改后的代码 这样执行的结果就会不一样

学习笔记 从class指令文件中理解java的多态是如何实现的

 

 

这是编译之后的class的内容

Classfile /E:/ali/demo/jvmxuexi/bin/com/haojiangbo/demo/TestClass.class
  Last modified 2018-8-2; size 1255 bytes
  MD5 checksum 0daedcc0bab3cec5d669373374ac3271
  Compiled from "TestClass.java"
public class com.haojiangbo.demo.TestClass
  SourceFile: "TestClass.java"
  InnerClasses:
       static #34= #42 of #1; //A=class com/haojiangbo/demo/TestClass$A of class
 com/haojiangbo/demo/TestClass
       static #38= #45 of #1; //B=class com/haojiangbo/demo/TestClass$B of class
 com/haojiangbo/demo/TestClass
       static abstract #23= #57 of #1; //P=class com/haojiangbo/demo/TestClass$P
 of class com/haojiangbo/demo/TestClass
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             //  com/haojiangbo/demo/TestClass
   #2 = Utf8               com/haojiangbo/demo/TestClass
   #3 = Class              #4             //  java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          //  java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          //  "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/haojiangbo/demo/TestClass;
  #14 = Utf8               sayHello
  #15 = Utf8               (Lcom/haojiangbo/demo/TestClass$P;)V
  #16 = Fieldref           #17.#19        //  java/lang/System.out:Ljava/io/Prin
tStream;
  #17 = Class              #18            //  java/lang/System
  #18 = Utf8               java/lang/System
  #19 = NameAndType        #20:#21        //  out:Ljava/io/PrintStream;
  #20 = Utf8               out
  #21 = Utf8               Ljava/io/PrintStream;
  #22 = String             #23            //  P
  #23 = Utf8               P
  #24 = Methodref          #25.#27        //  java/io/PrintStream.println:(Ljava
/lang/String;)V
  #25 = Class              #26            //  java/io/PrintStream
  #26 = Utf8               java/io/PrintStream
  #27 = NameAndType        #28:#29        //  println:(Ljava/lang/String;)V
  #28 = Utf8               println
  #29 = Utf8               (Ljava/lang/String;)V
  #30 = Utf8               p
  #31 = Utf8               Lcom/haojiangbo/demo/TestClass$P;
  #32 = Utf8               (Lcom/haojiangbo/demo/TestClass$A;)V
  #33 = String             #34            //  A
  #34 = Utf8               A
  #35 = Utf8               Lcom/haojiangbo/demo/TestClass$A;
  #36 = Utf8               (Lcom/haojiangbo/demo/TestClass$B;)V
  #37 = String             #38            //  B
  #38 = Utf8               B
  #39 = Utf8               Lcom/haojiangbo/demo/TestClass$B;
  #40 = Utf8               main
  #41 = Utf8               ([Ljava/lang/String;)V
  #42 = Class              #43            //  com/haojiangbo/demo/TestClass$A
  #43 = Utf8               com/haojiangbo/demo/TestClass$A
  #44 = Methodref          #42.#9         //  com/haojiangbo/demo/TestClass$A."<
init>":()V
  #45 = Class              #46            //  com/haojiangbo/demo/TestClass$B
  #46 = Utf8               com/haojiangbo/demo/TestClass$B
  #47 = Methodref          #45.#9         //  com/haojiangbo/demo/TestClass$B."<
init>":()V
  #48 = Methodref          #1.#49         //  com/haojiangbo/demo/TestClass.sayH
ello:(Lcom/haojiangbo/demo/TestClass$P;)V
  #49 = NameAndType        #14:#15        //  sayHello:(Lcom/haojiangbo/demo/Tes
tClass$P;)V
  #50 = Utf8               args
  #51 = Utf8               [Ljava/lang/String;
  #52 = Utf8               a
  #53 = Utf8               b
  #54 = Utf8               SourceFile
  #55 = Utf8               TestClass.java
  #56 = Utf8               InnerClasses
  #57 = Class              #58            //  com/haojiangbo/demo/TestClass$P
  #58 = Utf8               com/haojiangbo/demo/TestClass$P
{
  public com.haojiangbo.demo.TestClass();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>
":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       5     0  this   Lcom/haojiangbo/demo/TestClass;

  static void sayHello(com.haojiangbo.demo.TestClass$P);
    flags: ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #16                 // Field java/lang/System.out:Ljav
a/io/PrintStream;
         3: ldc           #22                 // String P
         5: invokevirtual #24                 // Method java/io/PrintStream.prin
tln:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 5: 0
        line 6: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       9     0     p   Lcom/haojiangbo/demo/TestClass$P;

  static void sayHello(com.haojiangbo.demo.TestClass$A);
    flags: ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #16                 // Field java/lang/System.out:Ljav
a/io/PrintStream;
         3: ldc           #33                 // String A
         5: invokevirtual #24                 // Method java/io/PrintStream.prin
tln:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 8: 0
        line 9: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       9     0     p   Lcom/haojiangbo/demo/TestClass$A;

  static void sayHello(com.haojiangbo.demo.TestClass$B);
    flags: ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #16                 // Field java/lang/System.out:Ljav
a/io/PrintStream;
         3: ldc           #37                 // String B
         5: invokevirtual #24                 // Method java/io/PrintStream.prin
tln:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 11: 0
        line 12: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       9     0     p   Lcom/haojiangbo/demo/TestClass$B;

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #42                 // class com/haojiangbo/demo/TestC
lass$A
         3: dup
         4: invokespecial #44                 // Method com/haojiangbo/demo/Test
Class$A."<init>":()V
         7: astore_1
         8: new           #45                 // class com/haojiangbo/demo/TestC
lass$B
        11: dup
        12: invokespecial #47                 // Method com/haojiangbo/demo/Test
Class$B."<init>":()V
        15: astore_2
        16: aload_1
        17: invokestatic  #48                 // Method sayHello:(Lcom/haojiangb
o/demo/TestClass$P;)V
        20: aload_2
        21: invokestatic  #48                 // Method sayHello:(Lcom/haojiangb
o/demo/TestClass$P;)V
        24: return
      LineNumberTable:
        line 14: 0
        line 15: 8
        line 16: 16
        line 17: 20
        line 18: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      25     0  args   [Ljava/lang/String;
               8      17     1     a   Lcom/haojiangbo/demo/TestClass$P;
              16       9     2     b   Lcom/haojiangbo/demo/TestClass$P;
}