赞
踩
发现一道有趣的试题,可以加深对多态实例化子类调用方法的理解,如下:
- 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);
- }
- }
- }
该题主要考的是对面向对象多态的理解,本题中最主要的是遵循一个原则:调用方法都是实例化后的子类的重写方法,除非明确指定super.xx或者子类没有该方法时,才会调用父类的同名方法。
在这道题中,首先构造了一个new B()的B类实例,进入B类中,构造器中super(5)调用父类带参构造器,执行setValue(v);,注意!这里的调用者为B类【遵循调用方法都是实例化后的子类的重写方法原则】,进入B类的setValue方法,B类该方法中明确指定调用父类的方法:super.setValue(2 * value) => 2*5=10传入进去,此时父类value值为10。
紧接着,B类继续执行setValue(getValue()- 3);,首先执行getValue()方法,在该方法中:
1.首先value++,即10+1=11,但因为try...finally是在方法体中,后面还有finally,要等finally执行完后,才会return返回该值(finally执行操作对value值的改变不会影响到return返回的value值)。
2.在finally中,调用了setValue方法,注意!这里的调用者仍然是B类【遵循调用方法都是实例化后的子类的重写方法原则,并且这里使用了this关键字,指定了调用当前对象的方法】。
3.子类的setValue方法中,同上,明确指定调用父类的方法 => 11*2=22,即父类的value值为22。
4.因此,finally这里输出22,然后return执行,返回value值11(给到方法,同时父类A的value值也为11)。
执行完getValue方法,回过头继续执行setValue(getValue()- 3),通过上面得知,getValue的返回值为11,即11-3=8,再调用B类的setValue方法 => 2*8=16传入父类的setValue方法中,此时父类的value值为16.
接下来执行new B().getValue()中的getValue()方法,由于B类没有getValue()方法,因此进入父类的该方法中:
最后,System.out.println(new B().getValue());会将getValue()的返回值打印出来,即输出17.
最终结果输出:22 34 17
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。