Java初始化的实质:
首先要明白“初始化”这个概念。所谓初始化就是把该对象的属性赋为默认值、把控件设为默认状态、把没准备的准备好。
然而,初始化也分为以下几种情况:
1.带属性的构造器,在用该构造器实例化一个新的对象时,会同时给该对象的属性赋值。
2. 定义某个属性时给其赋予初值
3. 非静态代码块中的初始化。需要说明的是静态代码块只在类创建时执行一次直到该类的销毁,而非静态代码块在每次实例化新的对象时总会被执行。
其中,情况2和3会早于情况1的执行,而2和3的执行顺序与他们所在源程序中的排列顺序相同。
执行顺序:静态代码块 > 非静态代码块 > 构造方法(这跟本篇博文没有直接关系,但这应该作为常识,被熟记于心)
以下是一个小例子:
public class TestField {
private int age;
private String name;
public TestField(int age,String name) {
System.out.println("执行构造器");
this.age=age;
this.name=name;
}
static{
System.out.println("静态初始化块");
}{
System.out.println("执行非静态初始化块");
weight=2.0;
}
//定义时指定初始值
double weight=2.3;
@Override
public String toString() {
return "TestField [age=" + age + ", name=" + name + ", weight="
+ weight + "]";
}
public static void main(String[] args) {
// TODO Auto-generated method stub
TestField tf=new TestField(22, "KITTY");
System.out.println(tf);
TestField tf2=new TestField(30, "tom");
System.out.println(tf2);
}
}
以上代码输出结果为:
-----------------------------------------------------------
静态初始化块
执行非静态初始化块
执行构造器
TestField [age=22, name=KITTY, weight=2.3]
执行非静态初始化块
执行构造器
TestField [age=30, name=tom, weight=2.3]
-----------------------------------------------------------------------
令人困惑的一点,可能大多数人认为weight的值应该是2.0,而不是2.3;那么,为什么呢?
实际上,定义实例变量时指定的初始值、初始化块中为实例变量指定初始值语句的地位是平等的,当经过编译器处理后
它们都被提取到构造器中,也就是说,对于语句:double weight=2.3;
实际上会被分为以下两次来执行:
(1) double weight;创建Java对象时,系统根据该语句为该对象分配内存
(2)weight=2.3;这条语句会被提取到构造器中执行
而在源代码中weight=2.0;语句位于double weight=2.3;语句之前,所以在初始化完成时,weight的值是2.3;
如果你还不明白,请继续读:
在编译器处理后,实质上类似于以下过程:
...{
double weight;
weight=2.0; //在源代码中靠前,所以先被提取到编译器
weight=2.3;//在源代码中靠后,所以后被提取到编译器
}...
当然,如果你较真,你仍然不服,可以在命令行编译源代码时用javap命令来验证:
步骤如下: