class Base {
// 定义了一个名为i的实例变量
private int i = 2; public Base() {
this.display();
} public void display() {
System.out.println(i);
}
}// 继承Base的Derived子类
class Derived extends Base {
// 定义了一个名为i的实例变量
private int i = 22; // 构造器,将实例变量i初始化为222
public Derived() {
i = 222;
} public void display() {
System.out.println(i);
}
}public class Test {
public static void main(String[] args) {
// 创建Derived的构造器创建实例
new Derived();
}
}运行结果是:0
求大牛解释一下原理。

解决方案 »

  1.   

    同样的问题:http://bbs.csdn.net/topics/390256394
      

  2.   

    package test;class Base {
        // 定义了一个名为i的实例变量
        private int i = 2;
     
        public Base() {
         System.out.println("Base中:"+i);
            this.display();
        }
     
        public void display() {
         System.out.println("Base中dis:"+i);
            System.out.println("我被多态了啊"+i);
        }
    }
     
    // 继承Base的Derived子类
    class Derived extends Base {
        // 定义了一个名为i的实例变量
        private int i = 22;
     
        // 构造器,将实例变量i初始化为222
        public Derived() {
         System.out.println("Derived中:"+i);
            i = 222;
        }
     
        public void display() {
         System.out.println("Derived中dis:"+i);
            System.out.println("是我吗?"+i);
        }
    }
     
    public class Test {
        public static void main(String[] args) {
            // 创建Derived的构造器创建实例
            new Derived();
        }
    }运行结果是:
    Base中:2
    Derived中dis:0
    是我吗?0
    Derived中:22
    加了几个输出会好看一点
    我的理解是 new Derived();时候会递归调用父类构造方法,父类的构造方法又调用了子类的display()方法,这时候的i还是0吧,不很清楚为什么是0,大神指点吧...共同学习,输出的就是子类的那个display()方法的i
    debug的时候出现了两个i,一个是属性的一个等于0的就看到这些了....
      

  3.   

    new Derived();
    此时,程序是这样走的:
    1.进入Derived的构造方法: public Derived() {
    super();//这里隐含一个调用父类构造的语句。
    i = 222;
    }2.通过super()方法进入Base类的构造方法: public Base() {
    this.display();//因为多态的原故,这句会调用子类覆写的方法
    }3.调用Derived类的display()方法: public void display() {
    System.out.println(i);//此时,变量i还未被赋值,默认初始值是0,因此输出0
    }4.第三步执行完后,再继续执行Derived构造方法里的下一句:i = 222;//虽然变量i被赋值了,可是输出语句已经完成了。5.程序执行完毕.
      

  4.   

    其实这种例子最好还是自己试一下,多测试一下要比听别人讲的更明白。
    我刚开始也做错了,后来自己更改不同的条件测试了7,8次吧。也就懂了。
    首先,加上
    System.out.println("derived display:"+i);
    System.out.println("base display:"+i);
    输出的是derived display:0,知道调用的是子类的方法。父类的方法被子类重写了。
    然后
    private int k=22;
    public Derived(){
    k=222;
    }
    public void display(){
    System.out.println("derived display:"+i);
    }
    把Derived的i改成k,这时候输出i报错,也就说明其实没有i这个量。如果非要输出,只能输出0或者报错。然后再把Base的i改成Public,这时候输出2。
    这时候就说明是这道题做的功能实际上就是把子类的display方法代替了父类的那个display方法。
    剩下的就容易理解了吧?
      

  5.   

    class Base {
        // 定义了一个名为i的实例变量
       private  int i = 2;
     
        public Base()
        {
        System.out.println("父类的构造方法");
            this.display();
        }
     
        public void display() 
        { 
        System.out.println("父类的具体方法");
            System.out.println(i);
        }
    }
     
    // 继承Base的Derived子类
    class Derived extends Base 
    {
        // 定义了一个名为i的实例变量
        private int i = 22;
     
        // 构造器,将实例变量i初始化为222
        public Derived() 
        {
        System.out.println("子类的构造方法");
            i = 222;
        }
     
        public void display() 
        {
        System.out.println("子类的具体方法");
            System.out.println(i);
        }
    }
     
    public class Test12
    {
        public static void main(String[] args)
        {
            // 创建Derived的构造器创建实例
            new Derived();
        }
    }
    Derived继承了Base类,因此在new Derived();实例化的过程中,通过new关键字调用无参的构造方法(),Derived继承了Base类,Derived类先加载在JVM上,然后实例化生成对象,通过这个对象,会先调用父类的无参构造方法,然后再执行调用子类的构造方法
      

  6.   

    简单地说,creation of instace of class 的时候,首先会初始化父类及其该类的成员变量(注意此时是赋予“默认初始值”),
    然后初始化 参数列表中的变量(如果有),然后才执行其他语句。
      

  7.   

       总之,不能理解为一new instance of class 的时候,就执行里面的语句。
     
      

  8.   

    5楼正解。
    这是一个典型的有继承关系的类的初始化顺序问题。原理其实楼上有几位已经说得比较清楚了,下面我们来就题论题一下:首先从main方法开始,new Derived()就是要new一个Derived的对象,那么根据对象初始化的顺序,
    初始化子类Derived之前必须要初始化父类Base,那么由于在调用构造函数之前,成员变量是先于构造函数初始化的,这个时候Base里面的i已经有值了,是2。在Base构造函数里面, 只有一句:this.display(), 这个方法在Base的子类Derived也定义了,并且此次初始 化是由子类Derived发起的,所以实际上这个方法调用的是Derived里面定义的display,而不是Base自己的display(所以输出不是2)。
    而这个时候子类Derived还没有进行构造,因为此时父类Base才正在构造之中,所以子类Derived中的i还是0,而display正好打印出的是子类Derived的i,所以最后的输出是0.不知道能解释的清楚楼主的问题么? 
      

  9.   

    楼主在和我们开玩笑吧!
    我实测了一下,输出结果是输出2!
    1。《java核心技术卷1-基础知识》中说在使用new关键字实例化对象时,类的域(类的成员)会先于构造器被实例化。我实测了下,父类和子类的域会被几乎同时实例化,域实例化后的值是默认值。
    2.我实测了下,代码中对类的域的赋值语句会在构造器启动之后,但是在开始执行方法块中的第一条语句之前执行。
    3.子类的构造器在启动之后会先启动父类的构造器。(我知道“启动”这个词可能不够专业,但是我也不知道怎么描述。看的人懂就好。)
    4.this关键字是指向实例的引用。
    上面四点就可以解释这个测试类的输出结果了。
      

  10.   

    在构造方法里调用可被override的方法是非常sb的做法,