一道类的执行顺序的习题

题目:

牛客链接: https://www.nowcoder.com/questionTerminal/af8cf04602e045958d13d16d20a1bf02
Test.main() 函数执行后的输出是():

public 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;  
            } catch(Exception e){  
                System.out.println(e.toString());  
            } finally {  
                this.setValue(value);  
                System.out.println(value);  
            }  
            return value;  
        }  
    }  
    static class B extends A{  
        public B() {  
            super(5);  
            setValue(getValue() - 3);  
        }  
        public void setValue(int value){  
            super.setValue(2 * value);  
        }  
    }  
} 

选项:
A : 11 17 34
B : 22 74 74
C : 6 7 7
D : 22 34 17

由于这道题涉及到执行顺序比较多,所以我觉得个人需要记录一下帮助记忆.

在解题之前可以先看看简单的类的执行顺序https://blog.csdn.net/u012403290/article/details/68954928
本文解答过程参考:https://blog.csdn.net/zhumintao/article/details/53818972

代码运行过程:

运行代码,对于一个普通类来说会先执行他的静态代码块,然后是main()方法,然后是非静态代码块,然后是构造方法.

对于当前这个类(class Test),会先执行main方法
于是来到这一行:
在这里插入图片描述
在这一行中,会new一个B的对象,并且调用B的getValue方法,那么此时开始构造B的实例,进入B的构造方法
在这里插入图片描述
由于B继承自A,并且A没有无参构造,所以B必须显示调用A的构造方法,并且传入参数.下面就会进入到A的构造方法
在这里插入图片描述
可以看到,此时A的构造方法又会调用setValue方法,那么这里需要注意的是:
A类和B类都有一个setValue方法,但是此时我们是为了创建B的实例,所以这里仍然处于B的构造方法执行过程,所以会默认调用B的setValue方法,如果B中没有这个方法,那么就会调用A中的这个方法.

那么此时就会进入B的setValue方法
在这里插入图片描述
此时可以看到B又调用了父类的setValue方法,并且传入的参数是 2 * 5,下来进入父类的此方法
在这里插入图片描述
此时A中成员属性value就被值为2 *5 即 10,此时B的构造方法中,调用A的构造方法过程已经结束了,下面执行B构造方法中的setValue方法.
在这里插入图片描述
注意到B中的setValue方法又会调用getValue方法,但是B中没有这个方法,所有会调用父类A的getValue方法,下面就来到A的getValue方法.
在这里插入图片描述
那么此时A的getValue方法会给A的成员变量value自增,并且返回value,没有触发异常,然后会执行finally中的代码
在这里插入图片描述
运行到这里可以看到A中的value已经自增成了11,此时finally又会调用setValue方法,这里需要注意的是,this.setValue(value)中的this指的是B的实例的引用,因为现在还处于B的构造方法过程,所以会调用B的setValue方法.
在这里插入图片描述
此时B中的setValue方法会嗲用父类的setValue方法,并传入2 * 11
在这里插入图片描述
此时value就变成了22,此时this.setValue(value)就执行完了,最后输出value,22
在这里插入图片描述
到这儿getValue()方法就执行完了,但是需要注意的是,虽然此时value是22,但是在A的getValue方法的 try的代码块中,已经返回了value,并且返回时value的值为11,所以这个方法的返回值级已经保存下来了,是11,而就算finally中再次对value进行了改变,返回的值也不会被改变.
此时继续执行B类构造方法中的setValue(getValue() - 3)
执行时得到setValue(11 - 3)
即setValue(8)
接下来执行B的setValue方法.
在这里插入图片描述
B又调用A的setValue方法,并传入参数2 * 11
则进入A的setValue方法
在这里插入图片描述
此时value变为16
到这儿B类的构造方法就全部执行完了,也就是new B()
然后又调用了该对象 的getValue()方法,B类没有,但是父类A有,所以
在这里插入图片描述
继续try{ }、catch{ }、finally{ },成员变量value为16
然后value++,再返回
这时getValue()的返回值已经确定了,就是17
然后到finally{ },又是this.setValue(value)
这个this指的是B类的this,所以调用B类的setValue(int value).
在这里插入图片描述
又是super.setValue(2 * value),调用A类的setValue(),并把2 * 17作为参数传递过去
在这里插入图片描述
把参数赋给成员变量value,这时this.setValue(value)就执行完了,此时的value为34。最后输出value。
在这里插入图片描述
此时的getValue()方法的返回值是17,前面已经提到了
整个new B().getValue()已经结束了
最后又输出了getValue的返回值,也就是17
最后的输出结果是:
在这里插入图片描述
也就是先前的选项D

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值