Java中成员变量的初始化顺序浅析
在Java中,所有的变量在使用之前都得到恰当的初始化,对于方法的局部变量,如果在使用前没有初始化,编译时系统会提示错误而无法继续编译;对于成员变量,系统会提供默认值,对于基本类型,默认置为0,引用类型默认为 null。然而,在很多书中都提到,构造函数的主要功能是用来在创建对象时初始化对象, 即为对象成员变量赋初始。这很容易让人误以为成员变量是在构造函数中完成初始化,其实,在构造函数之前已经分配有默认值,只是在构造函数里,我们可以根据自己需要重新对其进行设置初始值。
在类的内部,定义变量的先后顺序决定了初始化的顺序,即使变量定义散步在方法之间,他们仍会首先得到初始化。
class A{
private int i;
private int n;
private String name;
A(){
System.out.println(" class A : in default constructor i= "+ i+ " name= "+name);
}
A(int i,String name){
System.out.println(name+" berore inintial i= "+ this.i);
this.i = i;
System.out.println(name+" after inintial i= "+ this.i);
this.name=name;
}
public void AtoString(){
System.out.println("i= "+ i +" n= " + n + " name= "+name);
}
public int getI(){
return i;
}
public int getN(){
return n;
}
public String getNanme(){
return name;
}
}
class B{
A a0 = new A();
A a1 = new A(1,"a1");
A a;
B( A a){
System.out.println("before inintial");
//此处因为 成员变量 a 未初始化 此时为 null 所以不能使用它 的方法
//this.a.AtoString();
this.a = a;
System.out.println("after inintial");
this.a.AtoString();
}
A a2= new A(2,"a2");
}
public class InitialzationTest{
public static void main(String[] args) {
// first
A a = new A(999,"objectforb");
B b = new B(a);
}
}
输出:
objectforb berore inintial i= 0
objectforb after inintial i= 999
class A : in default constructor i= 0 name= null
a1 berore inintial i= 0
a1 after inintial i= 1
a2 berore inintial i= 0
a2 after inintial i= 2
before inintial
after inintial
i= 999 n= 0 name= objectforb
由输出我们可以知道,在InitialzationTest 类中首先新建了一个A 的对象 a,然后新建B的对象,在新建B的对象的过程中,先新建A的对象 a0, 然后新建a1 , a2 最后才执行B的构造器。在这过程中,我们看a0 ,a0 使用的是默认构造器,没有对其成员变量进行人为初始化,系统给其基本类型的成员变量初始化为 0 ,引用类型的成员变量name 初始化为 null , 另外在B的构造器中,我们对其中一行代码进行注释,因为系统对其初始化为null ,因此不能调用其方法。