public class Test3 extends Test4{
int i = 30;
Test3(){
print();
i = 40;
}
public static void main(String[] args){
System.out.println(new Test3().i);
}
void print(){
System.out.println(i);
}
}
class Test4{
int i = 10;
Test4(){
print();
i = 20;
}
void print(){
System.out.println(i);
}
}
结果是
0
30
40为什么

解决方案 »

  1.   

    在实例化父类之前也就是new Test4()运行完成之前int i是没有初始化的,输出了默认值0
    在new Test3()的执行就解释不了了
      

  2.   

    System.out.println(new Test3().i);执行它时先创建父类对象执行父类的构造方法,调用print()
    方法但执行的是子类的print();方法而不是父类的。因为在子类中i没有被初始化所以i的值为0,然后创建子类的构造方法执行print()方法,因为这时i已经被初始化了所以输出的就是30。最后执行System.out.println(new Test3().i);输出的就是i最后的值40.
      

  3.   

    Are U Kidding?
    期待高手解答,debug了没弄明白
      

  4.   

    Are U Kidding?
    期待高手解答,debug了没弄明白
      

  5.   

    System.out.println(new Test3().i);
    因为Test3 extends Test4 所以test3中的print()覆盖了父类test4的print()方法,直接执行了print(),但是此时i没有从父类中继承下来,所以初始化初始化默认为0,当new Test3()时候 调用test3的构造函数,执行了print();在此之前i已经被初始化为i=30,所以输出的就是30。最后执行(new Test3().i);此时的i是构造函数里 在构造时候赋值为 i=40,所以只要是 new出来的 test3,其中的i值 就一定是40。。
      

  6.   

    简单的说 就是 0的产生 是产生于extends后的那一瞬间,i处于青黄不接的时候
      

  7.   

    看看java编程思想中第8章里面 有个 “在构造器中的多态”看看吧 
    讲 的就是这个问题
      

  8.   

    因为再new子类的时候调用父类的构造方法,恰好子类又重写了父类的print方法,所以父类的构造中调用了子类的print方法。而此时子类的构造还没执行到,所有成员变量均为初始值0。
      

  9.   

    也没做对,Debug了一下才明白1.当new Test3()时首先为新对象申请内存,然后为对象的字段初始化为默认值,即i=0;2.因为Test3继承自Test4,在Test3对对象内存进行任何造作之前,先调用Test4的构造函数,
      因为Java虚拟机必须确保当Test3操作的时候,对象中的数据是符合Test4对象规范的。 
     
    3.Test4的构造函数中调用了Print,因为多态的原因,执行了Test3中的print方法,此时
      i尚未进行任何赋值所以输出int的默认值04.Test4构造函数执行完之后,开始执行Test3的字段赋值语句,因为其执行顺序高于构造函数5.执行Test3构造函数
      

  10.   

    首先,如果把子类中的print方法改为print2,即
    public class Test3 extends Test4{
        int i = 30;
        Test3(){
            print2();
            i = 40;
        }
        public static void main(String[] args){
            System.out.println(new Test3().i);
        }
        void print2(){
            System.out.println(i);
        }
    }
    class Test4{
        int i = 10;
        Test4(){
            print();
            i = 20;
        }
        void print(){
            System.out.println(i);
        }
    }结果是
    10
    30
    40
    其次,再来说为什么方法不一样就会有不同的结果。这是因为方法相同时有个覆盖的问题,创建的是子类的实例new Test3(),不管中间要经过多少“曲折”,在这个过程中不管你在哪调用,其调用的结果只能是子类的方法(除非你用super).
    再次,就是初始化顺序的问题了。父类静态变量->父类静态初始化块->子类静态变量->子类静态初始化块->父类变量->父类初始化块->父类构造器->子类变量->子类初始化块->子类构造器
        知道了这些自然就明白了
      

  11.   

    public class Test3 extends Test4{
        int i = 30;
        Test3(){
            print();
            i = 40;
        }
        public static void main(String[] args){
            System.out.println(new Test3().i);
        }
        void print(){
            System.out.println("test3  "+i);
        }
    }
    class Test4{
        int i = 10;
        Test4(){
            print();
            i = 20;
        }
        void print(){
            System.out.println("test4   "+i);
        }
    }
    我开始也认为是10,30,40看了j2eemail的解释便用上面的代码测试了一下确实执行的是Test3中的print()
      

  12.   

    up,个人也觉得应该是覆盖的问题,父类构造方法调用的是子类的方法,而子类还未初始化i,所以第一个是0~
      

  13.   

    public class Test2
    {
    int i = 20;

    public Test2()
    {
    print();
    i = 1111;
    }

    void print(){
    System.out.println("print:" + i);
    }

    public static void main(String[] args)
    {
    System.out.println(new Test2().i);
    }}为什么这样,输出的值却不是0
      

  14.   

    这个问题,貌似Thinking in java里面讲过类的初始化过程应该是这样的
    1、JVM将类加载到内存。。这个时候所有的类都是以2进制0的形式存在的
    2、再慢慢的按照我们知道的初始化我们看这道题
    new Test3().i 的时候。。
    1、将Test3,Test4初始化成为2进制的0(也就是所有的东西都是0)
    2、初始化Test4的变量再调用Test4的构造器调用Print方法,注意由于这里面存在多态。所以调用的是Test3的print的方法。。所以由上面类的初始化过程我们可以看到。Test3是以2进制0的形式存在的(因为还没有被初始化)。所以这个时候调用Print方法,所以i是0(注意是2进制的0)。至于楼主问的第二道题那是因为只有1个类。。类会先初始化类的变量。。然后再初始化构造器。所以这个时候打印i。i已经是被初始化的了。所以我们总结出来:尽量让类平稳的度过构造阶段。不要在构造器内添加一些可能影响逻辑的方法