A.javapublic class A {
    A() {
print();
    }
    void print() {
System.out.println("This is A");
    }
}B.javapublic class B extends A {
    B() {
print();
    }
    void print() {
System.out.println("This is B");
    }
}Test.javapublic class Test {
    public static void main(String[] args) {
A b = new B();
b.print();
    }
}为什么输出结果是三行“This is B”呢?
按我的理解,实例化子类的时候应该先调父类的构造方法,在父类的构造方法中调用自身的print()方法,应该先输出“This is A”呀。请帮我详细解释一下。

解决方案 »

  1.   

    构造子类时先构造父类没错,但父类方法中调用print方法时一样会发生多态,因为是子类构造连锁的父类构造,我是这么理解的
      

  2.   


    b的实际类型是B,但声明类型是A。
    程序的执行流程是:
     
      1.b的声明类型为A,所以先调用A的构造函数A(),A()里调用print()
      b的实际类型是B,所以A()里的print()执行的是B中的,所以出现第一个 "This is B”
     
      2.new B()调用了B的构造函数B(),B()里又调用print(),是自己的print(),
       所以出现第二个"This is B”  3.调用b.print(),因为b的实际类型是B,所以调用的是B的print(),所以出第三个"This is B”咋都问一样的问题呢:http://topic.csdn.net/u/20110225/22/8cb93da0-6b08-4061-9b18-96a2fd7b4a21.htmlhttp://topic.csdn.net/u/20110226/12/63c74e40-0294-4851-9af8-a30b0a0c0dba.html
      

  3.   

    1楼对的。
    即便是在构造阶段,方法是已经准备好的,子类方法对父类方法的Override效果已经开始了。
    所以父类构造器中调用的依然是子类方法。
      

  4.   

    1。首先调用父类构造函数是对的,然后调用print方法
    2。print方法实现了多态调用了b的print方法.
    3。调用子类构造函数,调用print方法.
    4。显示调用print方法,一共三次。
    建议:学会逻辑分析,不要把好多东西搞到一起,要学会逐层次去看问题,你可以在eclipse中打断点自己看一下流程不就好了.
      

  5.   

    上面讲的都对,而且很详细,实际上就LZ这道题而言  A b = new B();和 B b = new B();没有区别,无论b的类型是什么,但是new的时候都是B类型的,所以无论是在构造方法里面还是在外面调print() 都将是B里面的
      

  6.   

    A的print方法已经被覆盖了, 所以逻辑上说,这个方法对B而言已经不存在了。B继承A, 从逻辑意义上说,A已经消失了,只有B,只是由于B来源于A,所以构造B前,必须先构造A.有没有发现一个问题,A的所有方法都可以重写,但是构造方法不能;所以我们说构造器更合适。总结,方法被覆盖后,这个方法已经不存在了(子类super.print调用例外,相当于把A的方法体搬到B而已。)
      

  7.   

    换句话说print方法被覆盖了,那么程序在运行的时候JVM会判断方法的运行时类型,然后就会唤起继承机制,从而决定了执行方法的最终版本,就是动态绑定的一个过程。而运行时类型就是看你new 的是哪种类型的
      

  8.   

    new B()的时候,先调了A的构造,因为A的print被B覆盖,
    所以调一下B的print(此时输出了一个"This is B"),
    然后再构造B自己,调自己的print(此时又输出了一个"This is B"),
    最后b.print()又调B的print(此时又输出了一个"This is B")