java 继承 多态 this super 结合魔鬼调用

编程入门 行业动态 更新时间:2024-10-09 12:27:12

java 继承 多态 this  super 结合<a href=https://www.elefans.com/category/jswz/34/1756740.html style=魔鬼调用"/>

java 继承 多态 this super 结合魔鬼调用

本来就是刷一个题 结果给我整晕了特此记录一下

先说结论: java 多态指的是运行时多态和编译时多态,编译时的多态呢比较好理解就是
根据实际参数的数据类型、个数和次序,Java在编译时能够确定执行重载方法中的哪一个。
运行时多态:也叫作动态绑定,一般是指在执行期间(非编译期间)判断引用对象的实际类型,根据实际类型判断并调用相应的属性和方法。主要用于继承父类和实现接口时,父类引用指向子类对象。这个是jvm 有一套规范的 一般我们听到的是 若是字类复写了父类的方法则优先调用字类的方法,否则调用父类的方法, 但是这个调用这要时刻记住(即是this 当前指向誰)否则就是下面这个题目直接把你绕傻

本来的题目是这样的; 问最后打印的是三个啥值

class Test {public static void main(String[] args) {System.out.println(new B().getValue());}static class A {protected int value;public A (int v) {setValue(v);}public void setValue(int value) {this.value= value;}public int getValue() {try {value ++;return value;} finally {this.setValue(value);System.out.println(value);}}}static class B extends A {public B () {super(5);setValue(getValue()- 3);}public void setValue(int value) {super.setValue(2 * value);}}
}

这里贴上我自己的理解 后面写晕了可能有不对的但是最底下有大神的解释可以自己去看,反正我是不想看了

package cn.source.utils;/*** @ClassName: aaa* @Description: TODO* @author: human* @date: 2021-03-10 10:10*/public class aaa {public static void main(String[] args) {//程序的入口// 1 执行这个 new B() 这个动作;System.out.println(new B().getValue());}static class A {protected int value;//2  new  B 之前 先执行A的构造方法public A(int v) {// 执行a 自己的setvaluesetValue(v);}// 5  第一次执行 set value 方法//13  第二次执行 setvalue 方法//20  第三次执行 setvalue  方法public void setValue(int value) {// 6 此时的value =2*5// 14  此时的value= 11*2//21    value = 2*8 16this.value = value;}//8 第一次被调用用 此时value 等于10//// 第二次被调用   此时value 等于16// 第三次被调用 此时的值是34public int getValue() {try {//9  10+1 =11value++;// 10  return 的作用 保留当前的这个值11但是必须把finally块儿里边的代码走完 11return value;} finally {//11// 真的狗 this的作用誰调用我,我就是誰 此时this字类B对象,然后。setValue 方法//  这个时候value  等于11  调用字类的方法 逻辑自己去看  这个时候设置的value 34 17this.setValue(value);//15 所以第一次在这个地方打印的就是22// 所以在这个地方打印的就是34// 最后一次调用打印的是17System.out.println(value);}}}static class B extends A {// 实例化b 对象执行改构造方法public B() {//  2//  显示的写了调用父类的构造方法,//  但是父类的构造方法里边是调用的setValue方法;//  此时运行时多态因为字类重写了父类的这个setValue 所以调用的时自己的 setValue 方法//  自己的setValue在内部还是调用的父类的setValue方法  通过super关键字显示的调用 只是参数变了 把这个值给了过去super(5);// 7//这个时候显示的调用了自己的setValue方法,//字类没有重写父类的getValue方法,运行时多态调用的是父类的getValue方法// get value 方法执行完毕之后  return 会保留当前的值  所以此时(11-3)8// 设置完毕之后value的值为16//16   getvalue 返回值为11//17  执行 11-3 =8setValue(getValue() - 3);}// 3 执行自己的 set value 方法//11   第二次执行自己的set value方法// 18  第三次执行自己的setvalue 方法此时的值为8public void setValue(int value) {// 4 在内部还是调用的父类的方法 只是参数变了 此时传给父类的set value 方法的参数是2*5//12  现在的值是 2* 11//19  调用父类的构造方法 此时传入的值为 2*8super.setValue(2 * value);}}
}

思考和解决这个题的主要核心在于对java多态的理解。个人理解时,执行对象实例化过程中遵循多态特性 ==> 调用的方法都是将要实例化的子类中的重写方法,只有明确调用了super.xxx关键词或者是子类中没有该方法时,才会去调用父类相同的同名方法。
Step 1: new B()构造一个B类的实例

此时super(5)语句调用显示调用父类A带参的构造函数,该构造函数调用setValue(v),这里有两个注意点一是虽然构造函数是A类的构造函数,但此刻正在初始化的对象是B的一个实例,因此这里调用的实际是B类的setValue方法,于是调用B类中的setValue方法 ==> 而B类中setValue方法显示调用父类的setValue方法,将B实例的value值设置为2 x 5 = 10。
紧接着,B类的构造函数还没执行完成,继续执行setValue(getValue()- 3) // 备注1语句。

先执行getValue方法,B类中没有重写getValue方法,因此调用父类A的getValue方法。这个方法比较复杂,需要分步说清楚:

调用getValue方法之前,B的成员变量value值为10。
value++ 执行后, B的成员变量value值为11,此时开始执行到return语句,将11这个值作为getValue方法的返回值返回出去
但是由于getValue块被try finally块包围,因此finally中的语句无论如何都将被执行,所以步骤2中11这个返回值会先暂存起来,到finally语句块执行完毕后再真正返回出去。
这里有很重要的一点:finally语句块中 this.setValue(value)方法调用的是B类的setValue方法。为什么?因为此刻正在初始化的是B类的一个对象(运行时多态),就像最开始第一步提到的一样(而且这里用了使用了this关键词显式指明了调用当前对象的方法)。因此,此处会再次调用B类的setValue方法,同上,super.关键词显式调用A的setValue方法,将B的value值设置成为了2 * 11 = 22。
因此第一个打印项为22。  
finally语句执行完毕 会把刚刚暂存起来的11 返回出去,也就是说这么经历了这么一长串的处理,getValue方法最终的返回值是11。 

回到前面标注了 //备注1 的代码语句,其最终结果为setValue(11-3)=>setValue(8)
而大家肯定也知道,这里执行的setValue方法,将会是B的setValue方法。 之后B的value值再次变成了2*8 = 16;
Step2: new B().getValue()

B类中没有独有的getValue方法,此处调用A的getValue方法。同Step 1,

调用getValue方法之前,B的成员变量value值为16。
value++ 执行后, B的成员变量value值为17,此时执行到return语句,会将17这个值作为getValue方法的返回值返回出去
但是由于getValue块被try finally块包围而finally中的语句无论如何都一定会被执行,所以步骤2中17这个返回值会先暂存起来,到finally语句块执行完毕后再真正返回出去。
finally语句块中继续和上面说的一样: this.setValue(value)方法调用的是B类的setValue()方法将B的value值设置成为了2 * 17 = 34。
因此第二个打印项为34。
finally语句执行完毕 会把刚刚暂存起来的17返回出去。
因此new B().getValue()最终的返回值是17. 

Step3: main函数中的System.out.println

将刚刚返回的值打印出来,也就是第三个打印项:17

最终结果为 22 34 17。

更多推荐

java 继承 多态 this super 结合魔鬼调用

本文发布于:2024-02-07 05:42:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1753347.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:魔鬼   多态   java   super

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!