class Depend { 
int i = 10; public Depend() { 
print();  
i = 20; 
} void print() { 
System.out.println("Depend=> " + i); 

} public class qdb extends Depend { 
int i = 30; public qdb() { 
print();  
super.print(); 
i = 40; 
} void print() { 
System.out.println("Target=> " + i); 

public static void main(String[] args)
{
new qdb();
}

解决方案 »

  1.   

    class Depend
    {
        int i = 10;
        public Depend()
        {
            print();
            i = 20;
        }    void print()
        {
            System.out.println("Depend=> " + i);
        }
    }
    public class Qdb extends Depend
    {
        int i = 30;
        public Qdb()
        {
            print();
            super.print();
            i = 40;
        }    void print()
        {
            System.out.println("Target=> " + i);
        }    public static void main(String[] args)
        {
            new Qdb();
        }
    }给大家整理一下,方便看
    自己答错了
      

  2.   

    Target=>30
    Depend=>10
    Depend=>20
      

  3.   

    Depend=> 10
    Target=> 30
    Depend=> 30
      

  4.   

    首先在new Qdb();的时候,因为Qdb继承于Depend,所以先执行Depend的构造方法打印10,然后Depend的实例的
    i赋值为20,然后执行Qdb的构造方法,调用print(),打印出30,在执行父类对象的方法print();因为父类对象
    的i已经变为20,所以就打印出20。
      

  5.   

    但是我的编译了是
    Target=> 0  // 这个0怎么回事啊
    Target=> 30
    Depend=> 20
      

  6.   

    不对阿
    我认为应该是
    Depend=>10
    Target=>30
    Depend=>20可是编译了怎么会是
    Target=> 0  
    Target=> 30
    Depend=> 20
      

  7.   

    我随便说一下哈,可能说不大清楚,反正这个问题本来就难说清楚的,各位慢慢捉摸了执行new Qdb();时,首先初始化超类的字段i(=10),接着调用超类的构造方法
        public Depend()
        {
            print();
            i = 20;
        }
    但是这个print()是调用Qdb类的,因为Qdb重写了这个方法,而此时Qdb中的i声明了但还没有赋值,int型缺省为0,所以就打了Target=> 0出来,然后给超类的i重新赋值20接着Qdb给i赋值30,然后再执行Qdb的构造方法
        public Qdb()
        {
            print();
            super.print();
            i = 40;
        }
    这个时候print()打印出Target=> 30就很正常了,super.print()就直接定位到超类里去了,因为超类的i已经被重新赋值20了,所以打印Depend=> 20如果想不明白的话可以把个类中的i字段重构一下,比如把其中一个改为j,其实这两个i完全没有任何联系。
      

  8.   

    第一个数出的是
    Target=0
    难道向上转型了? 
      

  9.   

    class Animal
    {
    public void eat()
    {
    System.out.println(getClass().getName()+"eat");
    }
    }
    class Dog extends Animal
    {
    public void eat()
    {
    System.out.println(getClass().getName()+"eat");
    }
    }
    class Pig extends Animal
    {
    public void eat()
    {
    System.out.println(getClass().getName()+"eat");
    }
    }
    public class qdb
    {
    public static void main(String[] args)
    {
    Animal a1=new Dog();
    a1.eat();
    Animal a2=new Pig();
    a2.eat();
    }
    }
    这个例子比较容易理解
      

  10.   

    刚才作了个实验
    确实 基类初始化,不管到根基类有多少层,每层的方法都会被最终导出类的方法override
      

  11.   

    我们顺着初始化的顺序来说
    首先程序从main方法开始执行,new Qdb(),这句话就是要new一个Qdb的对象,根据对象初始化的顺序,初始化子类之前必须要初始化父类,所以此时一系列的调用开始了
    1,调用Qdb的父类Depend类的构造函数,在调用构造函数之前,成员变量是先于构造函数初始化的,这个时候Depend里面的i已经有值了,它的值就是10,在Depend构造函数里面,我们看到的第一句是:print方法,这个print方法我们要注意,它在Depend的子类也定义了,并且此次初始化是由子类Qdb发起的,所以实际上这个print方法调用的是Qdb里面定义的print,而这个时候有意思的事情就出现了,此时子类还没有出生呢,因为这个时候父类才正在构造之中,所以子类中此时的i还是0,而print正好打印出的是子类的i,所以第一次输出是0;
    2,父类调用完子类的print后,把父类的i赋了值20,此时父类已经完全被构造出来了,马上就要开始构造子类了.
    3,同理,在调用子类的构造函数之前,子类的i被赋了初值30,然后进入子类的构造函数,此时调用的也是print,这个就非常好理解了,这个print肯定是子类自己的print方法了,此时i已经构造好,当然,此时输出的值是30;
    4,下一句super.print(),这句话显示的调用了父类的print方法,而此时父类的i已经在父类的构造函数里面改为20了,所以此次调用输出20.
    5,然后再把子类的i的值设为50.在以上过程中,如果掌握好了类的初始化顺序,是比较容易知道输出结果的.还有一点要记住,JAVA里面的方法是动态绑定的,而成员却是静态绑定的.父类里面调用的print之所以会输出0,就是因为print实际上调用的是子类的print,因为整个这场调用都是由new Qdb()这句话产生的.
      

  12.   

    说的很明白哦
    需要认真的体会一下java中的继承和重载才可以努力学习 这个0真是不容易想到。顶
      

  13.   

    qdb extends Depend ,实现了对print()方法的覆盖
    (覆盖一个方法意味着替换它的实现,这样在子类对象上调用该方法时,被调用的就是该方法的子类版本)
    所以Target=> 0 
    其它如下:
    Target=> 30 
    Depend=> 20
      

  14.   

    Target=> 0/*这个零还真是让我忽略了!*/
    Target=> 30
    Depend=> 20类的初始化顺序以已经渐渐的清楚很多了
      

  15.   

    Depend=> 10 
    Target=> 30 
    Depend=> 30
      

  16.   

    执行new Qdb();时,首先初始化超类的字段i(=10),接着调用超类的构造方法 
        public Depend() 
        { 
            print(); 
            i = 20; 
        } 
    但是这个print()是调用Qdb类的,因为Qdb重写了这个方法,而此时Qdb中的i声明了但还没有赋值,int型缺省为0,所以就打了Target=> 0出来,然后给超类的i重新赋值20 接着Qdb给i赋值30,然后再执行Qdb的构造方法 
        public Qdb() 
        { 
            print(); 
            super.print(); 
            i = 40; 
        } 
    这个时候print()打印出Target=> 30就很正常了,super.print()就直接定位到超类里去了,因为超类的i已经被重新赋值20了,所以打印Depend=> 20 
      

  17.   

    这以前讨论很多次了,关键还是java中类的初始化顺序和动态绑定问题,
    比如说print的第一次调用,当调用子类的构造函数时,先构造父类的,这样就先加载父类的成员变量
    但是调用父类构造函数中的print方法,这是this引用实际上是子类,同时子类由于这个方法,
    就直接调用子类的方法
      

  18.   

    这个0还真的有点深藏不露哈,开始还以为就是:
    Depend=>10;---Target=>0;
    Target=>30;√
    Depend=>20;√受教了哈。
      

  19.   


    这里有点疑问,如果说子类还没出生,那它又怎么知道子类的i是int型而自动初始为0呢?
      

  20.   

    执行顺序的理解: class Depend   
    {   
        int i = 10;   
        //1.调用父类构造函数   
        public Depend()   
        {   
            //2.调用了子类的print()方法,父类i = 10   
            print();   
            //4.此处父类i 赋值为 20   
            i = 20;   
        }   
      
        //8.由第4步知父类i = 20   
        void print()   
        {   
            System.out.println("Depend=> " + i);   
        }   
    }   
      
      
    public class Qdb extends Depend   
    {   
        int i = 30;   
        public Qdb()   
        {   
            //5.调用子类print()方法,子类 i = 30;   
            print();   
            //7.显示调用父类print()方法   
            super.print();   
            //9.此处子类i 赋值为 40   
            i = 40;   
        }   
      
        void print()   
        {   
            //3. 子类i已经被声明为int(默认值为0),未赋值   
            //6. 子类i已经被赋值为 30   
            System.out.println("Target=> " + i);   
        }   
      
        public static void main(String[] args)   
        {   
            new Qdb();   
        }   
    }  
    这里对第3步不理解,如果说i已经被int i = 30;声明为int,为什么还没赋值呢? 如果没被声明,又为什么会输出 0 呢? 难道说,子类成员变量的声明在父类构造函数之前,而赋值在父类构造函数之后?
      

  21.   

    一: 子类重写了父类的方法,父类的方法如同被蒙蔽了.
    二:执行的时候是先调用父类的无参数构造方法,然后再执行子类的方法.
    所以结果是:
    Target>=0,//这是因为子类重写了父类的方法,所以结果是由执行子类里的方法得来的.
    Depend>=30,//执行完了父类的无参数构造方法,然后执行子类的构造方法.
    Depend>=20;//super的用法是指调用父类里的构造方法.
      

  22.   

    受教了
    不过这样一搞,父类当中是否永远调用不到那些被子类扩展的方法了???看来对于父类中init之类可能被扩展的方法最好还是留空比较好。