Java多态性之引用变量的动态绑定和静态绑定

运行时多态性

建议参考文章
讲的很好

引用变量的动态绑定和静态绑定

先来看段代码

/**
 * @SuperClass是父类,SubClass是子类。父类和子类都有method和add两种方
 */
public class SuperClass {
    public void method(SuperClass superObj){
        System.out.println("SuperClass.method(SuperClass)");
    }
    public int add(SuperClass superObj){
        System.out.println("SuperClass.add(SuperClass)");
        return 0;
    }
}
class SubClass extends SuperClass{
    public void method(SubClass subObj){
        System.out.println("SubClass.method(SubClass)");
    }
    public int add(SuperClass superObj){
        System.out.println("SubClass.add(SuperClass)");
        return 0;
    }
    public int add(SubClass subObj){
        System.out.println("SubClass.add(SubClass)");
        return 0;
    }
}

/**
 * @调用这对父类子类,看看method和add方法的绑定结果
 */
public class test {
    public static void main(String[] args){
        SuperClass superObj = new SuperClass();
        SubClass subObj = new SubClass();
        SuperClass superRef1 = superObj;
        SuperClass superRef2 = subObj;
        superRef1.method(subObj);
        superRef1.method(superObj);
        superRef2.method(subObj);
        superRef2.method(superObj);
        System.out.println("--------------------------------------");
        superRef1.add(subObj);
        superRef1.add(superObj);
        superRef2.add(subObj);
        superRef2.add(superObj);
    }
}

运行结果是:

SuperClass.method(SuperClass)
SuperClass.method(SuperClass)
SuperClass.method(SuperClass)
SuperClass.method(SuperClass)
--------------------------------------
SuperClass.add(SuperClass)
SuperClass.add(SuperClass)
SubClass.add(SuperClass)
SubClass.add(SuperClass)

分析

先看method方法的实际调用

从结果上看出,method全部调用的父类,说明对于superRef1和superRef2来说,调用方法的确定发生在编译阶段。因为引用变量定义为父类,因此调用父类的method。

再看add方法的实际调用

superRef1调用父类的add,superRef2调用的是子类的add。这和编译阶段的两个变量的定义不同,说明add的实际调用发生在运行阶段。
我们之前说过,重写发生在运行阶段。在父类方法中,add发生重写。因此,可以推测,在编译过程中系统判定add方法发生重写,因此暂定调用父类add方法,但是没有绑定,直到运行阶段才实际绑定。

结论

对没有重写的方法的实际调用,发生在编译阶段。
对发生重写的方法的实际调用,发生在运行阶段。

再来看下add方法的调用

已经知道add的绑定发生在运行阶段,为什么superRef2.add(SubClass)也是调用的子类的add(SuperClass)方法,而不是add(SuperClass)呢?
这是因为在编译阶段supreRef2.add已经实现了对父类的add方法初次绑定,但是在编译时系统判定add方法发生重写,需要等到运行时才真正绑定,而在运行时superRef2已经变成了子类,系统去调用子类中被重写的add,也就是子类中的add(SuperClass),才出现这样的结果。


有些拗口,那么可以直接跳过,看下边的结论


结论

一切引用变量的方法的绑定都在编译阶段完成。如果没有或者参数不匹配,就会直接报错
但是具体到非静态方法(静态方法不会出现运行时多态)的实际调用时出现以下两种情况:
1、方法没有更精确的版本(重写就是提供了更精确的版本),那么一切方法的确定将在编译阶段完成。
2、如果方法有更精确的版本,那么方法的实际调用就会推到运行阶段完成,但是和编译阶段的预绑定又具有一致性。

出现的原因可能是java的内在优化机制,也体现了java追求更精确方法,更新方法的一种思想。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiangz201

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值