黑马程序员技术交流社区

标题: 一条把我搞残的题,各位请进,帮帮我!! [打印本页]

作者: 姚远    时间: 2012-5-11 05:47
标题: 一条把我搞残的题,各位请进,帮帮我!!
题如下:
  classA{
  private int a=1;
  }

  class B extends A{
  private int b=2;
  }

  public class C extends B{
  private int c=3;
  public static void main(String[] args){
  new C();
  }
  }
  其中,每个类都要进行自动初始化,指定初始化,调用构造器进行初始化,请问:这三个类的三个初始化的顺序是怎样的?最好能写出理由!!!先谢过!!

作者: 李啸    时间: 2012-5-11 06:38
当newC()的的时候首先去判断B类当程序去加载B的时候发现B类继承A类就去先实例化A类的再去实例化B类再去实例化C类
作者: 张小锋    时间: 2012-5-11 06:45
先初始化A,再初始化B,最后初始化C,想证实很简单,稍微改一下代码就可以:
class A{
public A() {
  System.out.println("A");
}
   private int a=1;
}
class B extends A{
public B() {
  System.out.println("B");
}
   private int b=2;
}
class C extends B{
public C() {
  System.out.println("C");
}
既然是涉及到面向对象嘛,我就用现实中的例子给你打个比方:
人的继承关系:先有爸爸,后有儿子,在后有孙子:
如果你想要孙子,首先你就要成为爸爸,---》相当于new A(),
然后你要有儿子,       ---》相当于new B(),
最后你的儿子又了儿子,  ---》相当于new C()
这样比方应该很明白了吧
作者: 黄坚声    时间: 2012-5-11 06:50
很显然在加载main方法后,静态变量不管父类还是子类的都执行了,然后才是父类和子类的的普通变量和构造器。这是因为,当要创建子类这个对象时,发现这个类需要一个父类,所以把父类的.class加载进来,然后依次初始化其普通变量和初始化代码块,最后其构造器,然后可以开始子类的工作,把子类的.class加载进来,在做子类的工作。

作者: 黄坚声    时间: 2012-5-11 06:50
另外在Java中子类中都会有默认的调用父类的默认构造函数即super(),当仅仅有默认构造函数里
Java替你做了,我们可以做个实验,如果在父类中注释掉默认构造函数,加一个有参的构造函数时,
如果子类中不加super(argument),此时会报语法错误


作者: 杨鹏    时间: 2012-5-11 09:38
不考虑继承,单纯的new C(),虚拟机会执行如下操作:
(1):将C.class文件加载到内存中。
(2):在堆内存中创建一个C类对象。
(3):把C类对象中的属性进行默认初始化。
(4):把C类对象中的属性进行显示初始化。
(5):调用构造代码块(如果没有,不执行这个操作)。
(6):调用构造函数进行初始化。
如果一个类继承了另一个类,那在该类的构造方法中如果不指定需要调用的父类的构造方法,系统会默认调用父类的无参构造方法。楼主提供的代码中:C继承B,B继承A。那么在new C()的时候,在调用构造方法的时候,会去调用B的构造,而B再去调用父类A的构造,按照这样的执行逻辑可知A会先初始化,然后是B,再者就是C。这个是个人理解,不妥之处,还请多指正。
作者: 小小企鹅    时间: 2012-5-11 10:10
父类的部分必须在子类创建完成之前就必须完整地成形。父类的构造函数必须在子类的构造函数之前结束。每个子类的构造函数会立即调用父类的构造函数,如此一路往上直到Object.等到Objcet完成后会回去执行构造函数。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2