如果一个类有父类,并且该类里面存在super、this、非静态代码块,静态代码块,静态变量,非静态变量,那么初始化这个类的时候顺序是什么?
示例:
package com.lx;
public class Son extends Parent
{
final static Son INSTANCE = new Son(2.8);
static double initCount =20;
double currentCount;
{
currentCount = 15;
}
static{
initCount =22.8;
}
public Son(){
System.out.println("执行son的无参构造");
}
public Son(double discount){
this();
System.out.println("执行son的构造函数");
System.out.println(currentCount);
currentCount = initCount - discount;
System.out.println(currentCount);
}
public static void main(String[] args)
{
System.out.println(Son.INSTANCE.currentCount);
// Son son = new Son(1.8);
}
}
package com.lx;
public class Parent
{
double a;
static double b ;
public Parent(){
System.out.println(a);
System.out.println(b);
System.out.println("执行parent的无参构造");
}
{
a = 2.33;
}
static{
b = 33.33;
}
}
顺序是首先调用父类的构造,然后进行static的和非static的初始化,这两步都合并到构造里面进行,初始化的赋值取决于在类里面的顺序,但是都在构造执行的前面执行。
如果一定要给个顺序:那么是这样
分配子类的变量空间赋值为null或者为0接着super父构造,父构造里面执行前先分配内存空间并赋值,执行构造然后回到子类,进行变量的赋值操作,顺序为类里面代码的顺序(指的是代码块和赋值语句的顺序),然后才会执行构造函数里面的内容。其中有一点:非静态的代码块以及实例变量的赋值语句,执行在构造函数内容之前,super之后。然而静态的代码块以及类变量的赋值语句,与new 构造无关,只和代码里面的顺序有关,但是
new 构造会触发static的赋值时机,即在类中从上到下进行static的赋值,如果static的变量赋值不是上面代码那样static Son INSTANCE = new Son(2.8);那么同样会在构造函数之前进行赋值,然后在调用构造函数内容。即像父类Parent输出那样,其中a=2.33 b=33.33 而不是想象中的a=2.33 b=0.0
但是子类Son里面,触发static初始化赋值时机后,从上到下开始赋值但是INSTANCE = new Son(2.8);执行构造 同样会触发static的变量赋值,但是发现必须要先执行new Son(2.8)进行INSTANCE赋值,但是initCount还没有进行赋值,只是简单的初始化分配了内存值为0.0,所以就输出了负数。
最后main里面执行Son son = new Son(2.8)的时候,仍然进行了两次对INSTANCE的赋值,第一次出现的就是负数,第二次出现的是正数了,因为initCount已经赋值了。
所以补充一点:构造进行初始化的时候,会对所有的静态和非静态代码块和赋值语句,进行赋值,这一步执行操作在super之后,构造函数内容之前。非静态代码块和实例变量赋值,无论如何都会执行,而静态的代码块和类变量赋值则不一定,这个可以把
final static Son INSTANCE = new Son(2.8);
修改为Son INSTANCE = new Son(2.8);
再执行的话,会发现一直在进行new Son(2.8)的操作,一直到抛出Exception in thread "main" java.lang.StackOverflowError异常,这说明构造初始化的时候,会强制性的进行非静态代码块或者实例变量的赋值。
posted on 2012-06-12 20:31
朔望魔刃 阅读(312)
评论(0) 编辑 收藏 所属分类:
java