class Father{
  private int i = 70;
  Father(){
  //  System.out.println("Inside father "+getClass().getName()+" construct!" + i);
  //  System.out.println(super.toString());
  }
  public void update(){
    i ++;
    System.out.println(getClass().getName() + ":" +i);
  }
}
class Son extends Father{
  public int i = 45;
  Son(){
    //System.out.println("Inside son "+getClass().getName()+" construct!" + i);
    //System.out.println(super.toString());
    // update();
    // super.update();
  }
}public class Grandson extends Son{
  public int i = 20;
  Grandson(){
   // System.out.println("Inside grandson "+getClass().getName()+" construct!" + i);
   // System.out.println(super.toString());
   // update();
   // super.update();
  }
  
  public static void main(String[] args){
    Grandson suntest = new Grandson();
    suntest.update();
  }
}

解决方案 »

  1.   

    虽然都是int i,但在不同的类中定义,它们之间没有任何联系啊。我是运行了程序,不过没觉得结果有什么不正常啊,呵呵
      

  2.   

    很简单啊,由于子孙类中都没有覆盖超类的update()方法,所以创建了
    Grandson类的对象后调用超类father的update()方法
      

  3.   

    不知道你是哪里想不通,最后输出的是Father里的 i
      

  4.   

    update()方法是Father中的方法
    而打印i的时候程序到了Father的领域之中此时i是70,i++就是71getClass()在Grandson中重写了,所以是
    Grandson:71
      

  5.   

    呵呵,我仔细看了各位的回贴.
    这个问题不应该这么简单的,我对C++类的内存模型比较熟悉,对JAVA类的内存模型不清楚,在网上查了很多也没有相关资料(不知道候捷老师能不能出一本<<深入浅出JAVA>>哈),方法应该是属于类的,不存在有哪个领域的问题,只存在隐藏this指针(static方法除外),suntest.update(); 其实在幕后应该是suntest.update(this); 而执行的具体方法应该是:
      public   void   update(){ 
            this.i   ++; 
            System.out.println(getClass().getName()   +   ":"   +this.i); 
        } 
    而正如getClass().getName()所示,this所指向的对象是Grandson,而不是Father,而字段是属于对象的,不属于类(static 除外,static成员变量是属于类的),所以说,this.i按理应该是Grandson隐藏父类的成员变量,在构造函数执行前被初始化成20!
    说了这么多,不知说清楚没有?还望兄弟高人们指点迷津.
    有哪位兄弟有确切的JAVA类内存模型也行.
      

  6.   

    JAVA的内存模型是,每个子类实例中都包含一个完整的父类实例,并依次类推。所以,Grandson的实例中包含一个Son的实例,Son的实例中包含一个Father的实例。在内存中,Son包含三个i的值,但你无法通过Son的实例访问其它两个i,原因是名称屏蔽,这完全是一个名称空间的问题,而不涉及覆盖。而update()方法由于没有被任何子类覆盖,所以它永远是绑定给Father的实例的。还有问题吗?
      

  7.   

    补充一下,getClass()是一个覆盖方法,是由编译器为每个类重写的,因此,getClass()方法和你定义的update()方法的绑定情况是截然不同的。
      

  8.   

    按Dan1980的说法,我是否可以这么理解,继承的方法是和实现它的父类实例绑定的,方法中所涉及的实例变量只针对该父类实例变量,它根本无法对子类所承继的字段(即子类实例变量)实行操作,除非在子类中override了该方法,实现了多态.
      

  9.   

    凡是private 的方法,都是默認是final 的
      

  10.   

    其实你把Father类中的i设成public还是一样的.