posts - 188,comments - 176,trackbacks - 0

大家先看下下面这段代码的结果应该是多少?
public class ParentObjectInit {
 public void test() {

 }
 public ParentObjectInit() {
    test();
 }
 public static void main(String[] args) {
    new ChildObjectInit();
 }
}

class ChildObjectInit extends ParentObjectInit {
   private int instanceValue = 20;
   public void test() {
     System.out.println("instance1 value is: " + instanceValue);
   }
}

结果调试出来是20还是0呢?

*******************************************************************
(1)类中属性缺省初始化和显示初始化:
*******************************************************************

public class ParentObjectInit {
 public void test() {

 }
 public ParentObjectInit() {
    test();
 }
 public static void main(String[] args) {
    //先调用父类ParentObjectInit 的构造器
    new ChildObjectInit();
 }
}

class ChildObjectInit extends ParentObjectInit {

  //属性显示初始化在调用本类构造器之后
   private int instanceValue = 20;

  //进入ChildObjectInit类的构造器后,instanceValue值为20
   public ChildObjectInit() {
     System.out.println("instance1 value is: " + instanceValue);
   }

  // 在调用ChildObjectInit类构造器前打印
   public void test() {
     System.out.println("instance1 value is: " + instanceValue);
   }
}

过程如下:

上面程序可以说明的是:直到调用完父类ParentObjectInit 的构造方法之后,接着才对其成员变量instanceValue 显式的初始化操作,即将赋值20。

上面代码中的private int instanceValue = 20;定义应看成两部分:第一部分是定义变量,第二部分是给变量赋值。非static属性定义(缺省初始化)位于父类ParentObjectInit 构造方法之前,非static属性显示赋值位于父类ParentObjectInit 构造方法之后。

在父类ParentObjectInit 的构造方法执行时,根据多态性,它会去调用子类中定义的test()方法,可是,这时候,子类中的成员变量还没执行显式初始化操作, 对于private int instanceValue = 20;定义,instanceValue 的值为默认的初始化值0,所以,这时候在test方法中打印出的值为0。

备注:
private int instanceValue = 20;改为static修饰,其结果就是20,因为static属性在构造器调用之前就已经初始化了,并之后不会改变,属于整个类共享。

*******************************************************************
 (2)类中对象初始化流程:
*******************************************************************

class Bowl {
   Bowl(int marker) {
     System.out.println("Bowl(" + marker + ")");
   }
}

class Cupboard {

  //非静态初始化块
 {
      Bowl b1 = new Bowl(1);
 }
  //静态初始化块
 static{
      Bowl b2 = new Bowl(2);
 }
 /**
  * 非静态实例属性
  */
 Bowl b3 = new Bowl(3);

 /**
  * 静态实例属性
  */
 static Bowl b4 = new Bowl(4);

 Cupboard() {
      System.out.println("Cupboard()");
 }

 void f3(int marker) {
      System.out.println("f3(" + marker + ")");
 }

 /**
  * 静态实例属性
  */
 static Bowl b5 = new Bowl(5);
}

class StaticDataInit {
    public static void main(String[] args) {
      Cupboard t3 = new Cupboard();
      t3.f3(1);
 }

 /**
  * 和在main()里面用Cupboard t3 = new Cupboard();结果等价
  */
// static Cupboard t3 = new Cupboard();
}

运行结果为:
Bowl(2)  先调用static初始化块
Bowl(4)  顺序初始化static属性b4和b5
Bowl(5)  ...
Bowl(1)  调用非static初始化块
Bowl(3)  调用非static实例属性
Cupboard() 调用类Cupboard的构造器
f3(1)  对象t3调用f3方法

备注:如果将上面程序最后一句 static Cupboard t3 = new Cupboard();
注释解开。


运行结果为:
//static Cupboard t3 = new Cupboard();初始化的结果
Bowl(2)
Bowl(4)
Bowl(5)
Bowl(1)
Bowl(3)
Cupboard()
//创建对象t3并调用方法f3的结果
Bowl(1)
Bowl(3)
Cupboard()
f3(1)
//说明static属性和static块只在对象第一次初始化或static属性第一次初始化时赋值,以后不变


************************************************************************
形如:

public class A{
    private int a = 100;
    public A(){
      //...
    }
    public static void main(String[] args){
      new A();
    }
}
//属性a的缺省值为0,在调用构造器A()之前,属性a的值是0。
//仅当调用到构造器A()后才将100显示地赋给属性a,之后再执行构造器中的逻辑。


总结:当一个类A中的对象a初始化时,依次先初始化其static初始化块,static属性,非static初始化块(...)和非static属性(缺省初始化)。然后再调用类A的构造器对A中的属性进行显示初始化。

 

posted on 2007-06-01 16:40 cheng 阅读(1228) 评论(0)  编辑  收藏 所属分类: JBS

只有注册用户登录后才能发表评论。


网站导航: