Java数据初始化顺序:
注:本文中描述的初始化顺序不涉及多态,继承等特性。
类的初始化顺序
1.当类的.class文件被载入后,有关静态初始化的所有动作都会执行,而且只执行一次(注意:初始化是有顺序的,一般顺序为代码中定义的顺序)
2.当使用new关键字穿件类的实例的时候,首先会在堆上为对象分配足够的存储空间。
3.划分出存储空间之后,这块存储空间会被清零,这一步就自动地为对象中所有的基本数据类型的变量都设置成了默认值。
4.执行所有出现于字段定义处的初始化动作。
5.执行构造器,即构造方法。
以上内容全部来自于《Java编程思想》一书。下面看实例讲解:
静态块,初始化子句和构造器的初始化
public class Shiyan{
Shiyan(){
System.out.println("className{............}");
}
{
System.out.println("{...............}");
}
static {
System.out.println("static{..........} ");
}
public static void main(String args[]) {
System.out.println("main{..........} ");
new Shiyan();
}
}
结果为:
static{..........}
main{........}
{...............}
className{............}
结果分析
上例说明,在静态块,初始化子句和构造器中,最先被加载的一定是静态块(main方法也是静态的),不论它处在代码的什么位置,其次是初始化子句,最后才是构造器。所以顺序为:静态块>>初始化子句>>构造器。
包括静态变量,普通成员变量的类的初始化
public class shiyan{
static int i=5;
static shiyan b = new shiyan();
shiyan(){
System.out.println("className{............}");
}
{
/* System.out.println("{...............}"+j);放在此处出错,报非法的向前应用。 */
j = 20;
/* System.out.println("{...............}"+j);放在此处也出错,报非法的向前应用。 */
}
int j =10;
static {
System.out.println("static{..........} "+i);
}
public static void main(String args[]) {
System.out.println("main{........}");
shiyan h = new shiyan();
System.out.println(h.j);
}
}
结果:
className{............}
static{..........} 5
main{........}
className{............}
10
结果分析
1.上文中,知道静态块加载顺序优先于其他任何属性或方法,此处同样适用于静态变量,即静态变量、静态块和静态方法是同一个等级的,在该等级中初始化的顺序取决于代码中书写或定义的顺序。但都优先于其他的属性和方法;
2.上面结果中没有先执行静态块中的输出语句,是因为定义了一个静态变量b,在为b初始化时调用了构造器,所以先执行了构造器中的输出语句,但是加载的过程还是静态的东西先加载;
3.在初始化子句内部,一旦试图打印变量j则会报错,因为初始化子句中只允许执行初始化操作,但是在初始化子句内部却可以对变量j赋值,说明初始化子句执行的时间为本文开头处所写的“类的初始化顺序中的第3项”之后,与第四项的执行优先级相同,顺序为书写顺序。初始化子句,顾名思义就是为变量执行初始化操作的子句,与变量申明处的初始化属于同一等级,执行顺序为代码书写的顺序,所以在此例中mian方法打印的变量j的值为10。
总结
最后得出的初始化顺序为:(静态块,静态变量,静态方法)>>(普通成员变量,初始化块)>>(构造器);在同一等级中初始化的顺序取决于代码中书写的顺序。