实例变量的初始化时机

来源:互联网 发布:男性捏脸数据 编辑:程序博客网 时间:2024/05/18 00:05

从从语法的的角度来看,程序可以在3个地方对实例变量执行初始化:

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

public 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 + ", weight=" + weight + "]";}}public class InitTest {public static void main(String[] args) {      Cat cat=new  Cat("Kimy", 2);      System.out.println(cat);      Cat c2=new Cat("Migo",4);      System.out.println(c2);}}
console:

执行非静态初始化块.执行构造器.Cat [name=Kimy, age=2, weight=2.3]执行非静态初始化块.执行构造器.Cat [name=Migo, age=4, weight=2.3]

上面程序中的粗体字代码代表Java对象的3种初始化方式:构造器、初始化块和定义变量时指定的初始值。每当程序调用指定构造器来创建Java对象时,该构造器必然会获得执行的机会。除此之外,该类所包含的非静态初始化块将会获得执行的机会,而且总是在构造器执行之前获得执行。
当程序执行①行代码创建第一个Cat对象的时候,程序将会先执行Cat类的非静态初始化块,再调用该Cat类的构造器来初始化该Cat实例。
注 意:
很多读者在看这个程序时可能会感到奇怪,会认为执行创建Cat对象后weight实例变量的值应该是2.0,而不是2.3。因为他们认为,double weight = 2.3;代码应该先获得执行。但实际上,定义变量时指定的初始值和初始化块中指定的初始值的执行顺序,与它们在源程序中的排列顺序相同。
定义实例变量时指定的初始值、初始化块中为实例变量指定初始值的语句的地位是平等的,当经过编译器处理后,它们都将被提取到构造器中。也就是说,对于类定义中的语句:
double weight = 2.3;
实际上会被分成如下2次执行。



(1) double weight;:创建Java对象时系统根据该语句为该对象分配内存。

(2) weight = 2.3;:这条语句将会被提取到Java类的构造器中执行。

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


1 0