分享一个简单又复杂的程序选择题

今天在牛客网刷题,看见一个非常简单又很复杂的题目,我现在来分享一下。

想要解锁更多新姿势?请访问我的博客

题目是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Main {
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);
}
@Override
public void setValue(int value){
super.setValue(2 * value);
}
}
}

题目让写出上述代码执行完成后的输出结果

这道题考的其实就是代码执行顺序的知识,比较基础的东西。首先,用IDEA打一下断点,如图:

首先走主函数,new B,进入B的构造方法

并将父类A传入5(当子类构造器中没有使用”super(参数或无参数)”指定调用父类构造器时,是默认调用父类的无参构造器,如果父类中包含有参构造器,却没有无参构造器,则在子类构造器中一定要使用“super(参数)”指定调用父类的有参构造器,不然就会报错。 )

调用父类的setValue方法,由于子类已将其重写,所以直接到子类{

敲黑板:

1.父类,子类之间转型的问题,当父类声明指向子类对象,会发生隐式向上转型。

2.编译时所参考的对象类型是声明对象所用的类型,而运行时则是参考对象实例化的类型。

3.当子类重写了父类的某个方法时,会将父类的方法进行隐藏,因此这边最后调到的都是子类重写的方法。

}

现在回到value=10

现在value是10,准备进入geiValue阶段

还是10

在这里返回value,此时value是11

try{}catch{}执行完一定要走finnally

value是22了

终于开始打印了,打印第一个数字:22

返回value =22

回到刚刚B那里,第一次返回的value是11,将11-3=8

将8*2=16得到value

回到主方法

再走一边getValue()

进入finally,再将value*2=34

第二个数字出来了,打印34,然后返回3

到这里主函数执行完成,但是注意了。第二次返回值是17,第三次是34。到了最后又输出了getValue()第二次的返回值,也就是17

所以整个过程执行完后的输出结果是22、34、17。。。。。。

这个题有些语句有点多余,譬如finally代码块后面return永远用不上。

这道题虽然饶了很多弯,但细细品味后其实并没那么难,考点是:

1.自类继承父类,调用方法时先是调用子类中的方法,如果没有就调用父类中的方法。

2.try{ }、catch{ }、finally{ }返回值的问题,一旦try{ }中返回了某一个值,如果finally有返回值,finally中的返回值会覆盖try的返回值,如果finally没有返回值,就是try中的返回值。

-------------本稿が終わる感谢您的阅读-------------