1 public class TestDemo01 { 2 private static TestDemo01 tester = new TestDemo01(); //step 1 3 private static int count1; //step 2 4 private static int count2 = 2; //step 3 5 public TestDemo01(){ //step 4 6 count1++; 7 count2++; 8 System.out.println("" + count1 + count2); 9 } 10 public static TestDemo01 getTester(){ //step 5 11 return tester; 12 } 13 14 public static void main(String[] args){ 15 TestDemo01.getTester(); 16 } 17 }
这是我在网上无意间翻到的一道面试题,很有意思。最后输出的结果是11
为啥最后输出的是11呢
a, 首先装载这个类,然后在链接的准备阶段(链接包括验证、准备、引用三个阶段),为所有类(静态)变量分配内存,设为为默认值(Test tester = null; int count1 = 0; int count2 = 0;)
b, 链接完成后,进行(类)初始化,按代码中声明顺序进行类(静态)变量的初始化,也就是先调用
- Java code
-
private static TestDemo01 tester = new TestDemo01(); //step 1
注:这里省略了基类初始化和<clinit>的相关细节。
c, 上述步骤中的new 触发Test类的实例化(对象创建),先在堆上分配内存,然后设置对象变量(本例中没有)为初始值,然后调用<init>,细节略过,简单来讲这里会导致构造方法的调用,也就是:
- Java code
-
public TestDemo01(){ //step 4 count1++; count2++; System.out.println("" + count1 + count2); }
很显然,这时候的count1和count2并没有被初始化,只是简单的被设置为默认值0(在链接的准备阶段)。所以打印出来的值总是11。