相信大家接触过许多的代码输出题,本次来看一个比较典型的输出题,本题综合考察了类的实例化和继承以及try块 的相关细节知识,只要把本题理解透彻,以后的这种类型题就不会再迷茫?!
package www.yy.exer.day7;
/**
* @Author : YangY
* @Description :
* @Time : Created in 10:46 2019/5/29
*/
public class Test {
public static void main(String[] args) {
System.out.println(new B().getValue());//1 //17
}
static class A {
protected int value;
public A(int V) {
setValue(V); //3
}
public void setValue(int value) {
this.value =value; //5(value=10) //11(value=18) //16(value=)
}
public int getValue() {
try {
value++; //7(value=11)
return value; //8,暂存value(11)值,先不返回 //13
}catch (Exception e) {
System.out.println(e.toString());
}finally {
this.setValue(value); //9
System.out.println(value); //12(value=22)
}
return value;
}
}
static class B extends A {
public B() {
super(5); //2
setValue(getValue() -3); //6 //14
}
public void setValue(int value) {
super.setValue(2*value); //4 //10 //15
}
}
}
分析:
- 首先,进入到主方法,执行第一条语句的print方法,在方法体的参数中为:new B().getValue(),则首先得执行new B(),即实例化一个B类对象,当实例化一个对象的时候,我们来到了 2;
- 都知道,当实例化一个子类的时候,必须先执行父类的构造方法,而且父类的构造方法有参数,所以子类的构造方法的第一行必须要使用super(参数)来执行父类构造方法;然后来到 3;
- 此时执行父类A类的构造方法,setValue(V),好了,这里有人就搞不清楚了,这里到底是执行A类中的setValue方法,还是执行子类B类覆写的setValue? ,当前对象是B类对象,所以会调用B类覆写的setValue方法,此时来到了 4;
- 这里明确使用了super关键字,所以又调用父类的setValue方法,来到 5;
- 这时将value值设置成了10;
- 我们已经执行完了父类的构造方法,此时来执行B类的构造方法,即执行6,这时我们得先执行该语句里的getValue方法,这方法没有被覆写,所以来到父类的getValue方法;
- 执行try块的第一句,value值变为11;
- 接下来执行return value语句,但是我们知道必须得执行finally,所以这里暂存此时value的值,等执行完fianlly块,再回到这返回value的值,千万注意的是,这里返回的value值是之前的值(⭐),就算finally块里把value值改变了,返回的还是当时存储的vaule值;
- 来到了finally块,同理还是执行子类的(因为当前对象是new的B类对象)setValue;
- 来到了子类setValue方法,接下来又执行super语句;
- 此时value的值被设置为了22;
- 输出value值22;
- 此时回到try块的return语句,这个函数返回11;
- 此时回到B类构造方法的第二行,我们已经取到了参数getValue的值,为11,减三为8,此时执行setValue(8);
- 在B类的setValue中,又来到父类的setValue;
- 此时将value值设为16;
- 到此为止,new B()就执行完了,此时来到17,执行该对象的getValue方法;
- 此处又重复7到13的步骤,这个函数最终返回17,finally中的输出为34;
所以最终输出:22
34
17Process finished with exit code 0