class Dad{
int i = 1;
void printI(){
System.out.println(i + " dad"); //     --------------a
}
Dad(){
printI();                       //     --------------b
}
}
class Son extends Dad{
    int i = 2;
void printI(){
System.out.println(i + " son"); //     --------------c
}
Son(){
printI();                       //     --------------d
}
}
public class ExtendsTest extends Son{
public static void main(String[] args){
   ExtendsTest eTest = new ExtendsTest();
   //eTest.printI();

}
按初始化顺序-先父类类构造函数后子类构造函数,应该是:
1, b处调用a处 输出: 1 dad;
2, d处调用c处 输出: 2 son;但是结果为什么是: 0 son
                   2 son
为什么Dad类中的printI()根本就没有被调用啊?

解决方案 »

  1.   

    对于ExtendsTest,它的类信息的方法区里只有一个方法,那就是继承了父类Son的重写了它的父类Dad的void printI()方法,即使调用Dad类的构造,也只是会调用本类的printI()。
      

  2.   

    因为你的写法不规范,要实现你预期的效果,需要在 printI 前加 private 关键字予以保护,否则默认作用域是 protected,就会出现后一个结果。
      

  3.   

    当父类的成员变量辈子类覆盖的时候被子类调用,默认为0或null
      

  4.   

    怎么不是2 2 SON
           2 2 SON
      

  5.   

    先说说java的动态绑定吧,ExtendsTest eTest = new ExtendsTest(); 
    eTest中的printI(),为什么绑定Son中的printI(),这个太简单了吧,
    反正由此例子可知,就是这么绑定的。eTest就一个printI()方法,无论代码执行到哪儿。
    这个是sun规定的。再说说初始化顺序,先调用Dad的构造函数,然后再调用son的构造函数,或者简单说法:先初始化父类,再初始化子类,这个lz是明白的。再看看
    void printI(){
    System.out.println(i + " son");
    }
    此处i,有一个隐式句柄this,你在那两个方法上都改成this.i,结果相同
    这个隐式句柄this,java老人都该知道。
    在执行dad的构造函数时,this.i并未初始化啊,java给了一个默认值0。
    在执行son的构造函数时,this.i就正确初始化为2了。这个题有点难度,但是java老人,应该还是能做对的,
    你给点分,他们才愿意解答,
    而我不过是为了验证自己的想法对不对,才写这个回复
      

  6.   

    这是因为多态的问题造成的
    首先,字段并不是多态的
    只有方法才是多态的
    对象的生成首先会开辟一个内存空间,并将所有的值清成为
    这里,也就是说Son.i与Dad.i都是0
    然后就从最基类开始初始化它字段,并调用构造方法
    这个时候在调用Dad的构造方法时,调用了printI的方法
    很不幸,这个方法重载了
    那就自然会调用Son.printI的方法
    在这个方法里的i值还没有正确初始化呢
    结果就输出了0
    这是一种意外的逻辑错误
    所以构造方法只用来做字段的初始化
    不要做其他事情,特别是调用可能被重载的方法
      

  7.   

    楼上的说得没错,是初始化的顺序问题
    初始化对象时首先初始化最高层次的父类的变量,然后执行构造函数,但是在执行dad的构造函数的时候,由于动态绑定,多态的关系,printI是调用son的printI,但是执行son的printI的时候,son 的i却还没被初始化(必须等夫类的初始化完成以后再执行子类的初始化),所以此时未初始化的i是0,当dad的初始化搞定以后再执行son的初始化,现给son的i初始化,然后再调用son的构造函数,故此时的printI 输出 2
      

  8.   

    楼上的说得没错,是初始化的顺序问题
    初始化对象时首先初始化最高层次的父类的变量,然后执行构造函数,但是在执行dad的构造函数的时候,由于动态绑定,多态的关系,printI是调用son的printI,但是执行son的printI的时候,son 的i却还没被初始化(必须等夫类的初始化完成以后再执行子类的初始化),所以此时未初始化的i是0,当dad的初始化搞定以后再执行son的初始化,现给son的i初始化,然后再调用son的构造函数,故此时的printI 输出 2
      

  9.   

    呵呵 因为是第一次发帖 没有分可以给 就只有在这里对gadFly1981, (ouyangyh), (hahapigzhu)等几位表示感谢了,特别是(ouyangyh), (hahapigzhu)我觉得你们的解释比较合理,gadFly1981说对自己的看法不太确定,可以借鉴一下他们的解释。