Test.main()函数执行后的输出是什么?

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);
        }
    }

}


本人看到此题,读着读着就一脸懵逼了,但是经过查阅资料以及大哥们的解答,学习到了很多,在此记录一下此题,帮助大家共同学习和进步。

  1. 在main()函数中,首先new B()实例,此时B类中的无参构造函数现实的调用了父类A的带参构造函数。
  2. 在父类A中的带参构造函数中,又调用了setValue(v)方法,但是在父类A和子类B中都有setValue(v)方法,并且此时正在初始化的是一个子类B的实例对象,根据java多态特性,此时会调用的是子类B中的setValue(v)方法,而不是父类A中的setValue(v)方法。
  3. 而在子类的setValue()方法又显示的调用了父类的setValue()方法,将父类中的value值设置为了2*5=10
  4. 继续执行B类构造方法中的setValue(getValue() - 3)方法。
  5. 在上面方法中先执行getValue()方法,而在子类B中,没有重写父类的getValue()方法,因此调用的是父类的getValue()方法。在父类的getValue()方法中,分为如下几步:
    1. 在执行getValue()方法之前,value值已经被设置为10。
    2. value++后,value的值为11
    3. 将value值return返回出去
    4. 紧接着执行finally中的代码,所以暂时性的将上一步中的value值存储起来。等到finally代码块执行完成后再正真的将value值返回出去。
    5. 在finally中,又执行了setValue()方法,此时执行的也是子类B中的setValue()方法,因为此时我们正在初始化的是子类B的实例对象。(Java运行时多态)
    6. 而在子类B中的setValue()方法中又显示的调用了父类A中的setValue()方法,此时的value值又被设置为了2*11=22
    7. 紧接着执行finally代码块中的输出语句,打印出value值为22
    8. 紧接着将try语句中的return语句进行返回,返回的是暂存的value值11
  6. 返回值11之后,继续执行子类B中的setValue()方法,此时setValue()方法中的参数值为11-3=8,在执行setValue()方法时,显示的调用了父类的setValue()方法,并将value值设置为了2*8=16
  7. 终于,我们执行完了main()方法中的new B()方法,此时的value值为16,紧接着调用main()方法中的new B()方法的后续的方法getValue()方法
  8. 调用getValue()方法,子类B中没有重写父类A的getValue()方法,所以实际上执行的时父类中的getValue()方法,步骤如下:
    1. 在执行getValue()方法之前,value值已经被设置为16。
    2. value++后,value的值为17
    3. 将value值return返回出去
    4. 紧接着执行finally中的代码,所以暂时性的将上一步中的value值存储起来。等到finally代码块执行完成后再正真的将value值返回出去。
    5. 在finally中,又执行了setValue()方法,此时执行的也是子类B中的setValue()方法,因为此时我们正在初始化的是子类B的实例对象。(Java运行时多态)
    6. 而在子类B中的setValue()方法中又显示的调用了父类A中的setValue()方法,此时的value值又被设置为了2*17=34
    7. 紧接着执行finally代码块中的输出语句,打印出value值为34
    8. 紧接着将try语句中的return语句进行返回,返回的是暂存的value值17
  9. 最后在main方法中打印返回的值,返回的值为17,打印17
  10. 最后控制台上的打印结果为22   34   17

具体流程就到此结束了,是不是感觉很麻烦,但是实际上很简单,相信你也看出来了,实际上就是对多态的理解,麻烦的就是调用过来调用过去就晕了,只要理清思路还是很简单的。

(注意:try语句中的返回值会先暂时保存,等待finally代码块执行完成后再将暂存的值返回,finally代码块中的代码不会影响暂时存储的返回值哦!)

本题的解析主要时参考了牛客网用户<可乐芒果柠檬>的解析,如有意见,请联系我删除。