下面代码的结果是什么:
java 代码
public class Test { private static Test test = new Test(); public static int num1; public static int num2=0; private Test(){
num1++;
num2++;
} public static Test getInstance(){
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
} 这道题目咋看很简单,就是考察java初始化的顺序,但是很容易做错(我就做错了),结果应该是1、0按照java初始化的顺序:首先静态初始化,然后定义初始化,然后是构造函数初始化,很简单吗,于是乎没张脑子般就写出了结果:1、1 分解一下这段代码执行的过程:java 代码
Test test = Test.getInstance(); java虚拟机看到需要用到Test了,于是开始满世界的找寻Test,黄天不负有心人,它终于找到了Test.class,然后开始加载......然后要对Test打扮一番,好让她出去见人啊,于是开始初始化:初始化顺序的总规则:首先静态初始化,然后定义初始化,然后是构造函数初始化;静态分为两种:
1、静态的成员变量
2、静态代码块 static{}一般来说首先初始化静态类变量,然后初始化静态代码块。如果某个类有父类:
那么初始化顺序是:
1、对父类进行静态初始化(初始化父类的静态成员变量或者静态代码块)
2、对子类进行静态初始化(初始化父类的静态成员变量或者静态代码块)
3、对父类进行定义初始化(初始化父类的成员变量)
4、对父类进行构造函数初始化
5、对子类进行定义初始化(初始化子类的成员变量)
6、对子类进行构造函数初始化注意:jvm只在首次使用某个类的时候对其类变量进行一次初始化!回到正题,jvm初始化Test的时候也是按照上面的顺序进行的:
1、ClassLoader加载Test.class,我自己理解这个时候Test.class中的三个静态变量已经被装载进内存,并分别赋予了初始值
null,0,0 (不知道这样理解对不对)
2、按照顺序对Test.class进行静态初始化,注意这里只对所有显示初始化的变量进行初始化!没有显示初始化的变量不再进行 初始化!比如num1没有被显示的初始化,不再参与这个初始化过程(不知道这个理解对不对)
所以首先初始化的是:
private static Test test = new Test();
3、初始化test变量的时候调用了Test类的构造函数,在Test构造函数中对两外两个静态变量num1、num2进行了++操作,这个 时候num1和num2的初始值应该都是默认值0!
这个时候num1和num2的值都是1
4、完成了对静态变量test的初始化后开始初始化num2,这个时候num1=1,但是num2=0!!如果把代码改为:java 代码
public class Test { public static int num1; public static int num2 = 0; private static Test test = new Test(); private Test() {
num1++;
num2++;
} public static Test getInstance() {
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
} 结果就是1、1了!
因为按照顺序,先初始化了num2,后初始化test!1、装载Test.class
2、给类变量分配空间,赋予初始值
test = null (指向null)
num1 = 0
num2 = 0
3、开始初始化显示赋值的变量(test、num2)
1)初始化num2,将num2赋值为0
2)初始化test
(1)对类Test进行初始化,因为类变量只初始化一次,所以这里不再需要对test进行初始化了
(2)Test没有实例变量,所以不需要初始化实例变量
(3)对Test进行构造函数初始化,对num1和num2进行++操作
(4)初始化完毕,在堆区开辟内存空间存储Test的实例。
3)这个时候num1 = 1,num2 = 1把代码改为:
java 代码
public class Test { private static Test test = new Test(); public int num1; public int num2 = 0; private Test() {
num1++;
num2++;
} public static Test getInstance() {
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
} 结果也是1、11、装载Test.class
2、给类变量分配空间,赋予初始值
test = null (指向null)
num1 = 0
num2 = 0
3、开始初始化显示赋值的变量(这里是test,因为num1和num2都不是静态的)
1)初始化test
(1)按照初始化顺序,构造Test的时候首先初始化类变量,因为类变量只初始化一次,
所以这里不再需要对test进行初始化了
(2)进行定义初始化,初始化num1 和 num2
(3)对Test进行构造函数初始化,对num1和num2进行++操作
(4)初始化完毕,在堆区开辟内存空间存储Test的实例。
3)这个时候num1 = 1,num2 = 1
网上看了,不是很理解,希望高手指点?
加红,加粗那句怎么理解,为什么前面两段不这样的初始化?
java 代码
public class Test { private static Test test = new Test(); public static int num1; public static int num2=0; private Test(){
num1++;
num2++;
} public static Test getInstance(){
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
} 这道题目咋看很简单,就是考察java初始化的顺序,但是很容易做错(我就做错了),结果应该是1、0按照java初始化的顺序:首先静态初始化,然后定义初始化,然后是构造函数初始化,很简单吗,于是乎没张脑子般就写出了结果:1、1 分解一下这段代码执行的过程:java 代码
Test test = Test.getInstance(); java虚拟机看到需要用到Test了,于是开始满世界的找寻Test,黄天不负有心人,它终于找到了Test.class,然后开始加载......然后要对Test打扮一番,好让她出去见人啊,于是开始初始化:初始化顺序的总规则:首先静态初始化,然后定义初始化,然后是构造函数初始化;静态分为两种:
1、静态的成员变量
2、静态代码块 static{}一般来说首先初始化静态类变量,然后初始化静态代码块。如果某个类有父类:
那么初始化顺序是:
1、对父类进行静态初始化(初始化父类的静态成员变量或者静态代码块)
2、对子类进行静态初始化(初始化父类的静态成员变量或者静态代码块)
3、对父类进行定义初始化(初始化父类的成员变量)
4、对父类进行构造函数初始化
5、对子类进行定义初始化(初始化子类的成员变量)
6、对子类进行构造函数初始化注意:jvm只在首次使用某个类的时候对其类变量进行一次初始化!回到正题,jvm初始化Test的时候也是按照上面的顺序进行的:
1、ClassLoader加载Test.class,我自己理解这个时候Test.class中的三个静态变量已经被装载进内存,并分别赋予了初始值
null,0,0 (不知道这样理解对不对)
2、按照顺序对Test.class进行静态初始化,注意这里只对所有显示初始化的变量进行初始化!没有显示初始化的变量不再进行 初始化!比如num1没有被显示的初始化,不再参与这个初始化过程(不知道这个理解对不对)
所以首先初始化的是:
private static Test test = new Test();
3、初始化test变量的时候调用了Test类的构造函数,在Test构造函数中对两外两个静态变量num1、num2进行了++操作,这个 时候num1和num2的初始值应该都是默认值0!
这个时候num1和num2的值都是1
4、完成了对静态变量test的初始化后开始初始化num2,这个时候num1=1,但是num2=0!!如果把代码改为:java 代码
public class Test { public static int num1; public static int num2 = 0; private static Test test = new Test(); private Test() {
num1++;
num2++;
} public static Test getInstance() {
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
} 结果就是1、1了!
因为按照顺序,先初始化了num2,后初始化test!1、装载Test.class
2、给类变量分配空间,赋予初始值
test = null (指向null)
num1 = 0
num2 = 0
3、开始初始化显示赋值的变量(test、num2)
1)初始化num2,将num2赋值为0
2)初始化test
(1)对类Test进行初始化,因为类变量只初始化一次,所以这里不再需要对test进行初始化了
(2)Test没有实例变量,所以不需要初始化实例变量
(3)对Test进行构造函数初始化,对num1和num2进行++操作
(4)初始化完毕,在堆区开辟内存空间存储Test的实例。
3)这个时候num1 = 1,num2 = 1把代码改为:
java 代码
public class Test { private static Test test = new Test(); public int num1; public int num2 = 0; private Test() {
num1++;
num2++;
} public static Test getInstance() {
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
} 结果也是1、11、装载Test.class
2、给类变量分配空间,赋予初始值
test = null (指向null)
num1 = 0
num2 = 0
3、开始初始化显示赋值的变量(这里是test,因为num1和num2都不是静态的)
1)初始化test
(1)按照初始化顺序,构造Test的时候首先初始化类变量,因为类变量只初始化一次,
所以这里不再需要对test进行初始化了
(2)进行定义初始化,初始化num1 和 num2
(3)对Test进行构造函数初始化,对num1和num2进行++操作
(4)初始化完毕,在堆区开辟内存空间存储Test的实例。
3)这个时候num1 = 1,num2 = 1
网上看了,不是很理解,希望高手指点?
加红,加粗那句怎么理解,为什么前面两段不这样的初始化?
public class Test { private static Test test = new Test(); public static int num1; public static int num2=0; private Test(){
num1++;
num2++;
} public static Test getInstance(){
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
}
public class Test { public static int num1; public static int num2 = 0; private static Test test = new Test(); private Test() {
num1++;
num2++;
} public static Test getInstance() {
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
}
public class Test { private static Test test = new Test(); public int num1; public int num2 = 0; private Test() {
num1++;
num2++;
} public static Test getInstance() {
return test;
} public static void main(String[] args) {
Test test = Test.getInstance();
System.out.println(test.num1);
System.out.println(test.num2);
}
}
整理了下,总共三段程序,为什么前面两段最后调用的不是构造函数呢?
希望能有帮助
第二个和第三个都是这样,带static的是顺序执行,不带的就是首先执行带static的 .
2.因为前面两段的num1 num2是类变量,当然不是实例化的时候初始化的,所以和3不一样啊
3.整理了下,总共三段程序,为什么前面两段最后调用的不是构造函数呢?
---------------------------------------------
当然是调用了构造函数的(是在主动初始化test这个类变量的时候),但是再调用之后,还要初始化类变量num1和num2而num1没有主动初始化,所以是1,而num2主动初始化为0,所以结果是1,0
又因为这个类是singleton模式的,所以只会实例化一个对象
1、将代码进行良好的格式化,以方便阅读。
2、在发帖文本框的上方单击“#”按钮,选择 Java
3、将代码粘贴到【code=Java】和【/code】之间。发出来的帖子就会是下面的效果:public class Hello { // 程序入口
public static void main(String[] args) {
System.out.println("Hello!");
}
}