class Base{
 
   int i;   Base(){
   add(1); 
   System.out.println(i);
 }
 
 void add(int v){
    i+=v;
    System.out.println(i);
 }
 
 void print(){
    System.out.println(i);
   }
}
class MyBase extends Base{
   MyBase(){
    add(2);
 }
   void add(int v){
     i+=v*2;
     System.out.println(i);
   }
}
public class TestClu {
  public static void main(String[] args) {
  
    go(new MyBase());
  //System.out.println();
 } 
    static void go(Base b){
    b.add(8);
   //b.print();
 }
}
我开始得出的结果是21,正确是22.Base的i执行完后是1.但我不知道i是在什么时候就变成2了。还有一个问题是,static void go(Base b)中,是父类引用指向子类对象,所以为什么不是调用Base的add()呢,解释应该是子类覆盖了add()吧。如果是这样的话为什么还用父类的类型呢?它是不是有什么优点呢

解决方案 »

  1.   

    程序流程是这样的:
        在主函数中,首先执行new MyBase(),在这个过程中,子类会首先调用父类的构造函数;在父类的构造函数Base()中,执行add()方法,这里需要注意,这个add方法由于是在新建MyBase对象时调用的,将会首先查找MyBase类中是否有此方法。所以,Base()函数中的add(1)实际上是
    void add(int v){
         i+=v*2;
         System.out.println(i);
       }
    此时i的值即为2。在打印两个2之后,父类构造函数执行完毕,执行子类的构造函数,即MyBase(),这里的add(2)当然也是子类的。i的值就变为了6。
    最后执行go函数,i即为22。
      

  2.   

    对于第二个问题,搞清楚b.add(8)的b是什么就清楚了。显然,这里的b是MyBase类的对象,当调b.add(8)时,当然首先是去查找MyBase类的add方法,如果没有,再往上使用Base类的add方法。