Java中实例变量的初始化时机

Java 1199℃

对于实例变量而言,它属于Java 对象本身,每次程序创建Java 对象时都需要为实例变量分配内存空间,并执行初始化。从程序运行的角度来看,每次创建Java 对象都会为实例变量分配内存空间,并对实例变量执行初始化。从语法角度来看,程序可以在3个地方对实例变量执行初始化:

  • 定义实例变量时指定初始值;
  • 非静态初始化块中对实例变量指定初始值;
  • 构造器中对实例变量指定初始值。

其中第1、2种方式(定义时指定的初始值和非静态初始化块中指定的初始值)比第3种方式(构造器中指定初始值)更早执行,但第1、2种方式的执行顺序与它们在源程序中的排列顺序相同。下面程序示范了实例变量的初始化时机。

class Cat 
{ 
      //定义 name、age两个实例变量 
      String name; 
      int age; 
      //使用构造器初始化 name、age两个实例变量 
      public Cat(String name , int age) 
      { 
            System.out.println("执行构造器"); 
            this.name = name; 
            this.age = age; 
      } 
      { 
            System.out.println("执行非静态初始化块"); 
            weight = 2.0; 
      } 
      //定义时指定初始值 
      double weight = 2.3;  
      public String toString() 
      { 
            return "Cat[name=" + name 
                  + ",age=" + age + ",weigth=" + weight + "]"; 
      } 
} 
public class InitTest 
{ 
      public static void main(String[] args)  
      { 
            Cat cat = new Cat("kitty" , 2);               //① 
            System.out.println(cat); 
            Cat c2 = new Cat("Jerfield" , 3);              //② 
            System.out.println(c2); 
      } 
}

上面程序演示了Java 对象的3种初始化方式:构造器、初始化块和定义变量时指定的初始值。每当程序调用指定构造器来创建Java对象时,该构造器必然会获得执行的机会。除此之外,该类所包含的非静态初始化块将会获得执行的机会,而且总是在构造器执行之前获得执行。

当程序执行①行代码创建第一个 Cat 对象的时候,程序将会先执行 Cat 类的非静态初始化块,再调用该Cat 类的构造器来初始化该Cat实例。执行完①行代码后该Cat对象的weight实例变量的值为2.3,而不是初始化块中指定的2.0。这是因为,初始化块中指定初始值,定义weight 时指定初始值,都属于对该实例变量执行的初始化操作,它们的执行顺序与它们在源程序中的排列顺序相同。在本程序中,初始化块中对weight 的赋值位于定义weight 语句之前,因此程序将先执行初始化块中的初始化操作,执行完成后weight 实例变量的值为 2.0;然后再执行定义weight 时指定的初始值,执行完成后weight 实例变量的值为 2.3。从这个意义上来看,初始化块中对weight 所指定的初始化值每次都将被2.3 所覆盖。当执行②行代码再次创建一个 Cat 对象时,程序将再一次调用非静态初始化块,相应的构造器来初始化Cat 对象。

很多人在看这个程序时可能会感到奇怪,会认为执行创建Cat 对象后weight 实例变量的值应该是2.0,而不是2.3。因为他们认为,double weight = 2.3;代码应该先获得执行。但实际上,定义变量时指定的初始值和初始化块中指定的初始值的执行顺序,与它们在源程序中的排列顺序相同。

经过上面分析不难发现:构造器、非静态初始化块、定义变量时指定的初始值,三者的作用完全类似,都用于对实例变量指定初始值。经过编译器处理之后,它们对应的赋值语句都被合并到构造器中。在合并过程中,定义变量语句转换得到的赋值语句、初始化块里的语句转换得到的赋值语句,总是位于构造器的所有语句之前;合并后,两种赋值语句的顺序保持它们在源代码中的顺序。

转载请注明:零五宝典 » Java中实例变量的初始化时机