更详细:https://www.cnblogs.com/jthr/p/15762527.html

1.子类重写父类方法

1.1父类

public class Father {

    public int num = 20;

    public int get()
    {

        System.out.println("father-get");

        return num;
    }


    public void fatherMethod(){

    }
}

 

1.2子类

 

public class Son extends Father{

    public int num = 10;

    public int get(){
        System.out.println("son-get");
        return num;
    }



    public static void main(String[] args) {
        Father s = new Son();
        System.out.println(s.num);
        System.out.println(s.get());

    }
}

 

1.3执行结果

20
son-get
10

可以看到s.num输出的是父类的值

get方法调用的是子类的方法,输出的是子类的值

 

1.4使用 javap -verbose查看Son.class文件

看main方法

 

 

 可以看到,

s.num
s.get

都是父类的字段和方法

那么在执行时,却是父类的字段,子类的方法呢?

 

2.方法调用

2.1分类

 Java 的方法调用有两类,动态方法调用与静态方法调用。静态方法调用是指对于类的静态方法的调用方式,是静态绑定的;而动态方法调用需要有方法调用所作用的对象,是动态绑定的。类调用 (invokestatic) 是在编译时刻就已经确定好具体调用方法的情况,而实例调用 (invokevirtual) 则是在调用的时候才确定具体的调用方法,这就是动态绑定,也是多态要解决的核心问题。

JVM 的方法调用指令有四个,分别是 invokestatic,invokespecial,invokesvirtual 和 invokeinterface。前两个是静态绑定,后两个是动态绑定的。本文也可以说是对于 JVM 后两种调用实现的考察。

2.2动态调用

上面的例子,编译时,s的类型是Father

invokevirtual 指令指向的是#10,也就是father的get方法

  而真正调用方法时,根据实例this得到对象实际上是Son,它会先去查找Son方法表中的方法,如果有,调用Son方法表中的方法,如果没有,向上查找父类的方法表,找到后,调用父类方法表中的方法。