天天看點

一道面試題 java_關于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 代碼

Test test = Test.getInstance();

java虛拟機運作到Test了,于是開始尋找Test,找到了Test.class,然後開始加載,于是開始初始化。

初始化順序的總規則:首先靜态初始化,然後定義初始化,然後是構造函數初始化;

靜态分為兩種:

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(即為結果)。

題目的延伸:

如果把代碼改為:

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

把代碼改為:

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,1

1、裝載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。