黑马程序员技术交流社区

标题: 关于对象初始化过程的一点总结,大家帮忙看看 [打印本页]

作者: 罗文杰    时间: 2012-6-3 12:17
标题: 关于对象初始化过程的一点总结,大家帮忙看看
本帖最后由 罗文杰 于 2012-6-3 12:22 编辑

今天群里看到小丰童鞋发了一段代码讨论对象实例化的过程,代码如下,我加了两条输出语句。 (由于比较卡)关于这段代码得出的总结在二楼……
  1. class Super {
  2.         int i = 10;
  3.         Super() {
  4.                         System.out.println("Super构造函数 is running");
  5.                 print();
  6.                 i = 20;
  7.         }
  8.         void print() {
  9.                 System.out.println(i);
  10.         }
  11. }

  12. class Sub extends Super {        
  13.                 int j = 30;
  14.         Sub() {
  15.                         System.out.println("Sub构造函数 is running");
  16.                 print();
  17.                 j = 40;
  18.         }
  19.         void print() {
  20.                 System.out.println(j);
  21.         }               
  22. }
  23. class Test2
  24. {
  25.         public static void main(String[] args) {
  26.                System.out.println(new Sub().j);
  27.         }
  28. }
复制代码
执行结果为:

未命名.jpg (7.56 KB, 下载次数: 20)

未命名.jpg

未命名.jpg (7.56 KB, 下载次数: 24)

未命名.jpg

作者: 罗文杰    时间: 2012-6-3 12:29
关于楼上的代码的总结:
1.设置成员的值为默认的初始值(0,false,null)。
2.调用对象的构造方法(但是还没有执行构造方法体)。
3.调用父类的构造方法。
4.使用初始化程序和初始块初始化成员。
5.执行构造方法体。

初始化的过程中第一步是设置成员的值为默认值,所以在父类调用子类方法打印j的值为0的原因,就在这里。

然后再讨论下 有静态代码块和非静态代码块的执行顺序。代码如下:
  1. class Super
  2. {
  3.         static int a = 0;
  4.         {
  5.                 System.out.println("Super非静态代码块 is running");
  6.                 a = 10 ;
  7.         }
  8.         static
  9.         {
  10.                 System.out.println("Super静态代码块  is running");
  11.                 a = 20;
  12.         }
  13.         Super()
  14.         {
  15.                 a = 30;
  16.                 System.out.println("Super构造函数 is running");
  17.         }
  18. }

  19. class Sub extends Super
  20. {
  21.         static int c = 0;
  22.         static
  23.         {
  24.                 c = 10;
  25.                 System.out.println("Sub静态代码块  is runnning and now c is " + c);

  26.         }
  27.         
  28.         {
  29.                 c = 20;
  30.                 System.out.println("Sub非静态代码块  is runnning and now c is " + c);
  31.         }

  32.         Sub()
  33.         {
  34.                 c = 30;
  35.                 System.out.println("Sub构造函数 is running and now c is " + c);
  36.         }
  37. }
  38. class Test
  39. {
  40.         public static void main(String args[])
  41.         {               
  42.                 //System.out.println(Sub.c);
  43.                 Sub s = new Sub();               
  44.                 System.out.println(s.c);
  45.                 //System.out.println(Sub.c);
  46.         }
  47. }
复制代码
执行结果为:



作者: 罗文杰    时间: 2012-6-3 12:41
本帖最后由 罗文杰 于 2012-6-3 23:44 编辑

关于有静态代码块以及非静态代码块的初始化对象的初始化过程
对象被JVM装载,执行父类的相关代码,如果有静态初始化,先执行静态初始化,且只执行一次,以后即使有该类实例化,也不会再执行;如果有静态代码块(以与静态初始化一样的方式执行),楼上所示代码中如果把注释地方取消则结果为:

这里可以看出静态代码块只执行了一次,后面子类实例化的过程中没有执行。

如果有new语句带来的实例化(静态代码块执行了一次,没有没有执行参照上面写的):
1.先为成员变量分配空间,设置成员的值为默认的初始值(0,false,null)
2.调用对象的构造方法(但是还没有执行构造方法体)
3.隐式或显式调用父类的构造方法(但是还没有执行构造方法体)
4.执行父类的非静态代码块
5.执行父类的构造方法。
6.使用初始化程序和初始块初始化成员。
7.执行子类的非静态代码块
8.执行子类的构造函数
9.然后其他代码。
作者: 杨海波    时间: 2012-6-3 12:49
这个是子类继承了父类然后关于初始化的问题:
我是这样理解的:
1,子类一定要访问父类中的构造函数。因为父类中的数据子类可以直接获取,所以子类子类对象在建立时,需要
先查看父类中如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定
2,子类默认都会访问父类中的空参数函数。因为子类每一个构造函数内第一行都有一句隐式的super();
3,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,但子类要保证至少有一个构造函数会访问父类中的构造函数

作者: 梁小波    时间: 2012-6-3 13:06
好贴,呵呵顶一个{:soso__10659464829293696901_2:}




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