从从语法的的角度来看,程序可以在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类的构造器中执行。经过上面分析不难发现:定义实例变量时指定的初始值、初始化块中为实例变量指定的初始值、构造器中为实例变量指定的初始值,三者的作用完全类似,都用于对实例变量指定初始值。经过编译器处理之后,它们对应的赋值语句都被合并到构造器中。在合并过程中,定义变量语句转换得到的赋值语句、初始化块里的语句转换得到的赋值语句,总是位于构造器的所有语句之前;合并后,两种赋值语句的顺序保持它们在源代码中的顺序。
新闻热点
疑难解答