java 继承之上——动绑机制详解

news/2024/12/5 12:00:15/

一、前言 :

在java 面向对象三大特性——继承篇中,我们说过java 中查找方法的顺序为 : 本类方法—>父类方法—>更高一级的父类—>......Object(顶层父类) 然而,在某些情况下,这样的原则也会被凌驾。今天我们要说的java动态绑定机制,就是这样一个区别于继承机制的例外。

二、特点 :

  1. 通过对象的形式调用方法时,该方法会和堆内存中真正的该对象——的内存地址绑定,且这种绑定关系贯穿方法的执行全过程。这就是所谓的“动态绑定机制”。

  1. 当通过对象的形式调用属性时,不存在动态绑定机制,符合继承机制——即java中查找变量的顺序 : 局部变量—>成员变量—>父类—>更高的父类—>......—>Object

三、演示 :

1.准备工作 :

up以Father类为父类,Son类为子类(仅用作演示,无实际意义)。以TestBinding为测试类。还是老规矩,为了代码简洁,up这次将Father类和Son类写在了TestBinding类的源文件中。(PS : 其实不应该把测试类和子父类放一块儿的,但是动绑机制需要更直观地对比才好理解,就先这么干了)。

注意,我们要怎么测试动态绑定机制呢?别急,先来看看代码情况 :

up首先在Father类和Son类定义同名的成员变量temp,并且在子父类中各自给出temp变量的获取方法——即temp的getter方法——getTemp();。然后,分别在父类和子类定义两个关于temp变量的计算方法add_temp() add_temp_EX() ,相当于Son类重写了父类这两个方法。其中 : 父类的add_temp() 方法子类的add_temp_EX()方法中要调用getTemp()方法。最后,在测试类中利用多态的方式调用这两个方法。

TestBinding类,Father类,以及Son类代码如下 :

package knowledge.polymorphism.auto_bind;public class TestBinding {      /** 测试类 */public static void main(String[] args) {//建立多态关系Father father = new Son();System.out.println(father.add_temp());System.out.println(father.add_temp_EX());}
}class Father {                  /** 父类 *///父类的成员变量int temp = 5;//父类temp变量的getter方法public int getTemp() {return temp;}//父类的两个关于计算temp变量的成员方法//方法一public int add_temp() {return getTemp() + 10;}//方法二public int add_temp_EX() {return temp + 10;}
}class Son extends Father {      /** 子类 *///子类的成员变量(与父类成员变量同名)int temp = 11;//子类temp变量的getter方法public int getTemp() {return temp;}//子类的两个关于计算temp变量的成员方法//方法一public int add_temp() {return temp + 100;}//方法二public int add_temp_EX() {return getTemp() + 1000;}
}

2.开始测试 :

在测试类中,有两条输出语句,是通过父类引用调用成员方法。我们知道,根据多态中成员方法的使用规则——编译看左,运行看左父类引用,说明编译类型是父类类型,而父类中定义了这两个方法,因此编译没问题,可调用;又因为多态关系——父类引用此时指向了子类对象,因此运行类型为子类,子类重写了父类的这两个方法,当然要优先调用子类中的方法

所以我们来看,当前情况下,子类add_temp() 方法返回的是temp + 100,根据java中属性的查找原则,现在该方法内并没有定义temp局部变量,且子类定义了自己的temp成员变量,因此返回的“temp + 10”中,temp = 11。所以调用第一个方法最后的返回结果是111

调用第二个方法 : 同理,子类add_temp()_EX 方法返回的是getTemp() + 1000,本类getTemp() 方法又返回了本类的temp变量。所以调用第二个方法最后的返回结果是1011

运行结果如下 :

看完演示①之后,可能就要有p小将personable小将,指风度翩翩的人)出来(挑刺儿)说理了 : 这tm(题目)演示的不就是继承篇讲得那一回事儿吗,看不出哪儿来的动态绑定机制😅

p小将你先别急,讲东西总是要铺垫的嘛。这不就来了?现在,我们在演示①的基础上,注释掉子类的add_temp() 方法,如下图所示 :

大家注意,本来我是优先调用子类的add_temp() 方法,但是现在它被注释掉了,没法儿用!因此,根据继承机制,现在要去调用父类的add_temp() 方法。up先把父类和子类的代码截图放下面,方便大家思考,就不用往上翻了,如下图 :

没错,现在我们要去调用父类的add_temp() 方法了,但是问题来了 : 父类的add_temp() 方法中调用了getTemp() 方法,那这时候的getTemp() 方法是用谁的呢?

这里就是一个初学者大概率犯错误的地方,如果没有了解过动态绑定机制,它们会想当然的认为 : 现在执行的是Father类中的add_temp() 方法,根据java中查找方法的原则,当然是使用Father类本类的getTemp() 方法了!所以,最后的返回值就是5 + 10 = 15,输出15。但是真的是如此吗 ?

运行结果如下 :

输出结果表明父类add_temp() 方法最后返回的不是5 + 10,而是11 + 10,这表明add_temp() 方法中调用的getTemp() 方法是子类中的getTemp() 方法为什么呢?

原因就是我们说的动态绑定机制,由于测试类中是通过father引用来调用方法,而它指向的对象是Son类对象。根据动态绑定机制,在调用add_temp() 方法时,father引用已经和它指向的对象绑定了,并且这种绑定关系会贯穿方法执行的全过程。因此,这里调用的getTemp() 方法是子类的方法,而不是父类的。

我们在演示②的基础下,把子类的add_temp_EX() 方法也给注释掉,如下图所示 :

与演示②同理,由于子类重写的add_temp_EX() 方法被注释掉,因此要使用父类的add_temp_EX() 方法。up还是将Father类代码和Son类代码的截图给大家放下面,就不用再往上翻了,如下图所示 :

那么问题又来了 : 此时调用add_temp_EX() 方法,返回的究竟是5 + 10呢,还是11 + 10呢?

相信大家现在就没啥疑问了,前面我们说了 : 调用属性时,不存在动态绑定机制,符合继承机制。因此,根据Java中查找属性的原则,这里的temp变量肯定是Father类本类的temp成员变量,也就是5。所以,最后输出的结果自然是5 + 10 = 15。

运行结果如下 :

🆗,我们的动绑机制就说到这里,大家一定要牢记动绑机制的两大特点感谢阅读!


http://www.ppmy.cn/news/22501.html

相关文章

【MySQL】MySQL中的日期和时间函数有哪些?元宵节杭州灯光烟花秀你去看了吗?

日期函数元宵节灯光秀时间和日期函数获取当前日期的函数和获取当前时间的函数获取当前日期函数UNIX时间戳函数返回UTC日期的函数和返回UTC时间的函数获取月份的函数MONTH(date)和MONTHNAME(date)获取星期的函数DAYNAME&#xff08…

算法刷题-插入区间、杨辉三角、移除链表元素

文章目录插入区间杨辉三角移除链表元素插入区间 给你一个** 无重叠的**_ ,_按照区间起始端点排序的区间列表。 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。 示…

若依框架---PageHelper分页(十)

在前几天的文章中,我们介绍了PageHelper的分页方法,研读代码定位到了ExecutorUtil.pageQuery(...)方法,并阅读到了其中的部分代码。 今天我们将看到重要的SQL修改代码。 getPageSql 我们接着看代码: if (!dialect.beforePage(…

【数模比赛】2023美国大学生数学建模比赛(思路、代码......)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

cmake构建动态库

文章目录前言代码库文件代码测试代码Linux下测试前言 linux下的动态库/静态库,以前就知道咋构建:头文件与库的关系。最近写win下动态库的时候,有些细节与linux下有点不同。 所以这篇文章简单介绍下,如果使用cmake构建一个可以跨…

git命令总结

1、git stash命令总结 git stash:命令会把所有未提交的修改保存到git堆栈(包括git add和未add的)。 git stash save "test-cmd-stash":作用同上,但可以给stash添加注释信息。 git stash --keep-inde:只会…

HTML基础学习(3)——认识表格

往期文章 HTML基础学习&#xff08;1&#xff09;——HTML基本标签HTML基础学习&#xff08;2&#xff09;——超链接和使用图像 # 1.表格基本组成 HTML中表格使用表格标签\和多个行\、表头\ 或单元格\组成。 标签描述<table>定义表格<caption>定义表格标题<…

【第十届“泰迪杯”数据挖掘挑战赛】B题:电力系统负荷预测分析 31页省一等奖论文及代码

相关链接 &#xff08;1&#xff09;【第十届“泰迪杯”数据挖掘挑战赛】B题&#xff1a;电力系统负荷预测分析 问题一Baseline方案 &#xff08;2&#xff09;【第十届“泰迪杯”数据挖掘挑战赛】B题&#xff1a;电力系统负荷预测分析 问题一ARIMA、AutoARIMA、LSTM、Prophe…