class text01{
public text01(int i){
System.out.println("Test01 of constractor : " + i);
}
}
public class text02 {
private text01 t1 = new text01(1);
private int n = 10;
public text02(){
System.out.println("Test02 of constructor : " + n);
}
private text01 t2 = new text01(2);
public static void main(String[] args) {
text02 test = new text02();
}
}
- 输出的结果为:
- Test01
of constractor : 1 - Test01
of constractor : 2 - Test02
of constructor : 10
通过输出,可见当生成Test02的实例test时,它并不是首先调用其构造方法而是先是成员变量的初始化,而且成员的初始化的顺序以成员变量的定义顺序有关,先定义的先初始化,初始化后再调用构造方法。其实成员变量的初始化,在类的所有方法调用之前进行,包括构造方法
当类中有Static 修饰的成员呢?测试下面一段代码:
- public
class Test03 ...{ -
private int i1 = printCommon(); -
private static int i2 = printStatic(); -
-
public Test03()...{ -
-
} -
public static int printCommon()...{ -
System.out.println("i1 is init!"); -
return 1; -
} -
public static int printStatic()...{ -
System.out.println("i2 is init!"); -
return 2; -
} -
public static void main(String[] args) ...{ -
Test03 t = new Test03(); -
} - }
-
- 输出结果为:
- i2
is init! - i1
is init!
可见static的成员比普通的成员变量先初始化。
我们都知道,如果一个类的成员变量没有在定义时,系统会给予系统默认的值,有=号的就直接给予右值,系统在给予初值和=号给予值这2中方式,在执行时间上有先后吗?为了测试,我编写了如下代码:
- public
class Test04 ...{ -
private static Test04 t1 = new Test04(); -
private static int i1; -
private static int i2 = 2; -
-
public Test04()...{ -
i1++; -
i2++; -
} -
-
public static void main(String[] args) ...{ -
Test04 t2 = new Test04(); -
System.out.println("t2.i1 = " + t2.i1); -
System.out.println("t2.i2 = " + t2.i2); -
} - }
- 我们先预计一下输出,可能有几种答案:2和3,3和3,2和2
- 执行代码后:
- t2.i1
= 2 - t2.i2
= 3
为什么是2和3呢?其实代码的执行顺序是这样的:首先执行给t1,i1,i2分别给予初始值null,0,0,再执行
Test04 t1 =new Test04(),这样i1++,i2++被执行,i1,i2都变为1,执行完毕后接着执行int i1; i1,i2的值仍然是1,1,当执行int i2 = 2时i2被赋予了值,即i1 = 1,i2=2;再执行Test04 t2 = new Test04(),i1,i2再执行++,此时i1 =2,i2 =3,输出i1,i2,结果就是:t2.i1 = 2,t2.i2 = 3。 通过上面的代码我们可以认为系统默认值的给予比通过等号的赋予先执行。
public class SuperClass {
static{
System.out.println("SuperClass of static block");
}
public SuperClass(){
System.out.println("SuperClass of constracutor");
}
}
public class SubClass extends SuperClass{
static{
System.out.println("SubClass of static block");
}
public SubClass(){
System.out.println("SubClass of constracutor");
}
public static void main(String[] args){
SuperClass t = new SubClass();
}
}
// SuperClass of static block
// SubClass of static block
// SuperClass of constracutor
// SubClass of constracutor
可见当父类,和子类有Static时,先初始化Static,再初始化子类的Static,再初始化父类的其他成员变量->父类构造方法->子类其他成员变量->子类的构造方法。
父 类上层还有父类时,总是先执行最顶层父类的Static-->派生类Static-->派生类 Static-->.......-->子类Static-->顶层父类的其他成员变量-->父类构造方法--> 派生类的其他成员变量 --> 派生类构造方法--> ...............-->子类其他成员变量-->子类构造方法
总结:
(1) 在一个不存在继承的类中:初始化static变量,执行static初始化快-->初始化普通成员变量(如果有赋值语句),执行普通初始化块-->构造方法
(2)在一个存在继承的类中:初始化父类static成员变量,运行父类static初始化块-->初始化子类static成员变量,运行子类static初始化块-->初始化父类实例成员变量(如果有赋值语句),执行父类普通初始化块-->父类构造方法-->初始化子类实例成员变量(如果有赋值语句)及普通初始化块-->子类构造方法。
注意:其中变量初始化(赋值)和初始化块的执行与相关语句在源码中的放置顺序一致,不过变量声明会最先执行,参考 http://www.189works.com/article-52232-1.html 。