class Insect{
private int i = 9;
protected int j;
Insect( ){
System.out.println("i = " + i + ",j = " + j);
j = 39;
}
private static int x1 = printInit("static Insect.x1 initialized");
static int printInit(String s) {
System.out.println(s);
return 47;
}
}public class Beetle extends Insect{
private int k = printInit("Beetle.k initialized");
public Beetle(){
System.out.println("k = " + k);
System.out.println("j = " + j);
}
private static int x2 = printInit("static Beetle.x2 initialized");
public static void main(String[] args) {
System.out.println("Beetle constructor");
Beetle b = new Beetle();
}
}
中,main函数的Beetle constructor在Insect和Bettle类中的静态变量被初始化后才打印
运行结果:
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
i = 9,j = 0
Beetle.k initialized
k = 47
j = 39
而class Insect{
private int i = 9;
protected int j;
Insect( ){
System.out.println("i = " + i + ",j = " + j);
j = 39;
}
private static int x1 = printInit("static Insect.x1 initialized");
static int printInit(String s) {
System.out.println(s);
return 47;
}
}class Beetle extends Insect{
private int k = printInit("Beetle.k initialized");
public Beetle(){
System.out.println("k = " + k);
System.out.println("j = " + j);
}
private static int x2 = printInit("static Beetle.x2 initialized");
}public class TestBeele {
public static void main(String[] args) {
System.out.println("Beetle constructor");
Beetle b = new Beetle();
}
}中main函数的打印语句会在Beetle和Insect中的静态变量被初始化前打印,
运行结果:
Beetle constructor
static Insect.x1 initialized
static Beetle.x2 initialized
i = 9,j = 0
Beetle.k initialized
k = 47
j = 39
为什么呢?望高手解答
不过呢如果是多线程下如果你的static比较耗时而请求又比较密集的话,你那样初始化会给你个未定义的错误呵呵。
class Insect{
private int i = 9;
protected int j;
Insect( ){
System.out.println("i = " + i + ",j = " + j);
j = 39;
}
private static int x1 = printInit("static Insect.x1 initialized");
static int printInit(String s) {
System.out.println(s);
return 47;
}
}public class Beetle extends Insect{
private int k = printInit("Beetle.k initialized");
public Beetle(){
System.out.println("k = " + k);
System.out.println("j = " + j);
}
private static int x2 = printInit("static Beetle.x2 initialized");
public static void main(String[] args) {
System.out.println("Beetle constructor");
Beetle b = new Beetle();
}
}
用上面的代码做例子讲讲JVM的运行过程: (1) 首先是运行包换了main()方法的主类Beetle,此时JVM会将Beetle.class进行加载,并在内存的方法区中开辟空间用来存放类静态成员数据,并设置默认值(比如int默认值为0)。然后调用初始化方法clinit()来对这些类静态成员数据进行初始化计算,比如上面的:private static int x2 = printInit("static Beetle.x2 initialized")。因此,第一次加载Beetle类并初始化就会运行上面的x2=....语句。
第一个打印的是:static Beetle.x2 initialized
(2)再加载Beetle类之后,JVM会再把Beetle的父类Insect加载进来,并同时开辟内存并初始化类静态成员变量,过程同上。因此,会执行private static int x1 = printInit("static Insect.x1 initialized");语句
第二个打印的是:static Insect.x1 initialized
(3)然后JVM会为main()方法创建一个栈帧并加入到栈中,并开始执行此方法中的指令。那么第一条指令就是一条打印语句,因此: System.out.println("Beetle constructor");
第三个打印的是:Beetle constructor
接着执行 Beetle b = new Beetle(); 将在堆中创建一个Beetle对象,实际上JVM会调用构造器和实例变量的初始化语句进行初始化。然而在执行Beetle对象的初始化之前,会首先调用其父类的构造器和实例变量的初始化语句。因此JVM会首先执行下面这几条语句。这里要注意,对于实例变量j而言,在没有初始化之前其值为默认值0.
private int i = 9;
protected int j;
Insect( ){
System.out.println("i = " + i + ",j = " + j);
j = 39;
}
第四条打印语句将是:i = 9,j = 0
当继承父类的实例变量初始化完毕之后,JVM会对Beetle类的实例变量开辟空间并进行初始化,此时调用下面的语句:
private int k = printInit("Beetle.k initialized");
public Beetle(){
System.out.println("k = " + k);
System.out.println("j = " + j);
}
因此后面将打印出:
Beetle.k initialized
k = 47
j = 39
主要区别的在jvm加载Beetle类的时机不同。
第一个因为他本身一个应用类,要运行main就必须先加载它。所有static的那些在main方面还没有执行的时候就执行了
第二个同理,在是在要new的时候才需要加载它。
打印顺序应是先static Insect.x1 initialized,
再static Insect.x2 initialized,应该先初始化基类的静态变量
第一次打印: static Insect.x1 initialized
(2)对父类初始化完毕之后,然后再进行Beetlt初始化类静态成员变量,过程同上。因此,会执行 private static int x2 = printInit("static Beetle.x2 initialized"); 第二个打印的是:static Beetle.x2 initialized