java中普通变量、静态变量、静态代码块初始化的顺序辨析(二)
println("static code ");
i = 47;
}
}
public class Test {
public static void main(String[] args) {
new Spoon(2);
}
}
/*
Spoon(1)
static code
Spoon(2)
*/
/*
如果写成
static{
System.out.println("static code ");
i = 47;
}
static Spoon s = new Spoon(1);
结果为:
static code
Spoon(1)
Spoon(2)
*/
分析:静态代码块跟静态变量都是类加载时进行初始化的(同等条件下,初始化顺序由书写顺序决定)
4.非静态代码块
[html]
class Spoon{
public Spoon(int maker) {
System.out.println("Spoon("+maker+")");
}
static int i;
static Spoon s = new Spoon(1);
static{
System.out.println("static code ");
i = 47;
}
int a;
//非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中
{
System.out.println("non-static instatnce");
a = 1;
}
}
public class Test {
public static void main(String[] args) {
new Spoon(2);
new Spoon(3);
}
}
/*
non-static instatnce
Spoon(1)
static code
non-static instatnce
Spoon(2)
non-static instatnce
Spoon(3)
*/
分析:
1.main函数执行new Spoon(2)语句,首先加载Spoon类,先初始化静态变量s,s调用new Spoon(1),此时类Spoon已经加载,所以不用管静态变量和静态代码块了,然后调用非静态代码块和构造函数,输出"non-static code,spoon(1)"。
2.初始化静态代码块,输出"static code"。
3.执行new spoon(2)语句输出“non-static instatnce,Spoon(2)“。
4.执行"new spoon(3)"语句输出”non-static instatnce,Spoon(3)”。
可以尝试调换静态变量s和静态代码块的顺序,发现只是1和2的先后顺序改变而已。
在看下面这个程序
[cpp]
class T{
public T() {
System.out.println("T constructor");
}
}
class Spoon{
public Spoon(int maker) {
System.out.println("Spoon("+maker+")");
}
int a;
//非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中
{
System.out.println("non-static instatnce");
a = 1;
}
T t1 = new T();
}
public class Test {
public static void main(String[] args) {
new Spoon(2);
}
}
/*
non-static instatnce
T constructor
Spoon(2)
*/
通过这个程序,可以发现非静态变量和非静态代码块顺序由书写顺序决定。
5.总结:
以Dog类为例
1.当第一次执行到需要使用Dog类时(如Dog d = new Dog),java首先通过寻找classpath来找到Dog.class,进行加载.
2.初始化Dog类的静态变量和静态代码块(按书写顺序,若静态变量或代码块中还有new Dog,此时不用再管静态变 量和代码块了,如第五个程序中的"static Spoon s = new Spoon(1)")。
3.
系统给类分配足够大的内存空间,初始化非静态变量和非静态代码块(顺序由书写顺序决定)
4.最后执行Dog类的构造函数。
5.以后如果还要new Dog类对象时(不是第一次使用了),重复3和4的步骤,不会再去初始化静态变量和静态代码 块了。
大家可以自己写程序实验一下。
6.子类继承父类时的初始化顺序
1.系统启动时,首先初始化父类和子类的static变量和块
2.初始化父类的普通变量,调用父类的构造函数
3.初始化子类的普通变量,调用子类的构造函数
7.附记
由于个人能力有限,第一次学习只了解这些了,有什么错误,请多多指教。