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);
}
}
}
上述程序的输出是22 34 17,
解析:1程序启动时进入main方法程序入口,创建B类的实例对象然后调用其继承A类的getValue方法,
2调用B类的构造方法时,显示的调用了父类的构造方法,在父类的构造方法中调用了setValue()方法,这时需要注意,
由于子类B重写了父类A的setValue,由于Java实现了动态绑定机制(也就是在运行时根据对象的信息来绑定到底调用哪个类上的方法),这时调用的是B类的setValue方法,此时属性value的值是10
3当经过上面一个步骤后,父类对象已经安全完整的构造好了,接下来子类对象还未完全构造好,此时调用setValue(getValue-3),getValue调用的是A类上的方法(B类继承而来),这里就是接下来的关键所在:首先value此时为10,在try块中实现value++,然后进入finally块中调用setValue方法(这时还是调用的B类中的方法,因为this指代的是B类的对象,在调用getValue方法中编译器会自动传入一个this参数到getValue方法,这个事情是编译器帮我们做好了,我们不能这么做),那么此时value为11,调用setValue后value的值就为22了,所以第一次输出22,但是在try块中return返回的是value++以后的值,也就是11,所以此时B类构造器里调用setValue(11-3)以后,value的值就为16
4经过2,3两个步骤,子父类对象基本构建完毕,此时在main方法中调用新建B类对象的getValue方法,value先自增,return暂存value的值17,随后进入finally,调用setValue(),然后输出value的值为17*2=34,最后返回value的值为17
这个程序很好的讲解了动态绑定机制同时还顺带说了下try-finally的特性