第一題
public class Test3 {
public static Test3 t = new Test3();
{
System. out .println("blockA" );
}
public Test3() {
}
static{
System. out .println("blockB" );
}
public static void main(String[] args) {
Test3 t1 = new Test3();
}
}
答案:
blockA
blockB
blockA
解析:
- JVM調用mian方法,發現Test類還沒有被加載
- 加載Test類,類加載的準備階段,會給類變量賦默認值,所以t1的默認值爲null
- 類加載的最後一個階段是初始化,先執行new Test();
- 實例化一個Test對象,先執行構造代碼塊,再執行構造函數,所以先輸出“blockA”
- 然後執行靜態代碼塊,輸出“blockB”
- 當Test被加載完成後,執行main方法中的new Test();和第四步類似,先執行構造代碼塊,再執行構造函數,所以輸出“blockA”
第二題
class SingleTon {
private static SingleTon singleTon = new SingleTon();
public static int count1;
public static int count2 = 0;
private SingleTon() {
count1++;
count2++;
}
public static SingleTon getInstance() {
return singleTon;
}
}
public class Test {
public static void main(String[] args) {
SingleTon singleTon = SingleTon.getInstance();
System.out.println("count1=" + singleTon.count1);
System.out.println("count2=" + singleTon.count2);
}
}
答案:
count1=1
count2=0
解析:
- main方法引發SingleTon類的加載
- 在類加載準備階段給靜態變量賦默認值,singleTon=null,count1=0,count2=0
- 然後執行初始化操作(給靜態變量賦值+執行靜態代碼塊),執行new SingleTon();先執行構造函數,此時count1=1,count2=1
- 繼續賦值count1,count2。因爲count1沒有賦值操作,估count1不變,count2爲0
第三題
public class Parent {
int a = 10;
static int b = 11;
// 靜態代碼塊
static {
System.out.println("Parent靜態代碼塊:b=" + b);
b++;
}
// 代碼塊
{
System.out.println("Parent代碼塊: a=" + a);
System.out.println("Parent代碼塊: b=" + b);
b++;
a++;
}
// 無參構造函數
Parent() {
System.out.println("Parent無參構造函數: a=" + a);
System.out.println("Parent無參構造函數: b=" + b);
}
// 有參構造函數
Parent(int a) {
System.out.println("Parent有參構造函數: a=" + a);
System.out.println("Parent有參構造函數: b=" + b);
}
// 方法
void function() {
System.out.println("Parent function run ……");
}
}
public class Child extends Parent {
int x = 10;
static int y = 11;
// 靜態代碼塊
static {
System.out.println("Child靜態代碼塊:y=" + y);
y++;
}
// 代碼塊
{
System.out.println("Child代碼塊: x=" + x);
System.out.println("Child代碼塊: y=" + y);
y++;
x++;
}
// 構造函數
Child() {
System.out.println("Child構造函數: x=" + x);
System.out.println("Child構造函數: y=" + y);
}
// 方法
void function() {
System.out.println("Child function run ……");
}
}
public class Test {
public static void main(String[] args) {
Child demo = new Child();
demo.function();
System.out.println("…………………………………………………………………………………………………………………………");
Child child = new Child();
child.function();
}
}
答案:
Parent靜態代碼塊:b=11
Child靜態代碼塊:y=11
Parent代碼塊: a=10
Parent代碼塊: b=12
Parent無參構造函數: a=11
Parent無參構造函數: b=13
Child代碼塊: x=10
Child代碼塊: y=12
Child構造函數: x=11
Child構造函數: y=13
Child function run ……
--------------------------------
Parent代碼塊: a=10
Parent代碼塊: b=13
Parent無參構造函數: a=11
Parent無參構造函數: b=14
Child代碼塊: x=10
Child代碼塊: y=13
Child構造函數: x=11
Child構造函數: y=14
Child function run ……
解析:
1.執行new Child()觸發父類Parent的加載
2.Parent類加載的準備階段爲類變量(靜態變量)分配內存,賦默認值b=0
3.Parent類加載的最後一個階段,初始化類變量(靜態變量),執行靜態代碼塊
4.b=11,輸出‘Parent靜態代碼塊:b=11’,執行完畢後b=12
5.然後加載Child類
6.Child加載準備階段,未類變量賦默認值y=0
7.Child加載最後階段,初始化類變量執行靜態代碼塊
8.y=11,輸出‘Child靜態代碼塊:y=11’,執行完畢後y=12
9.然後實例化Child對象
10.先執行父類Parent的構造函數
10.1-初始化非類變量a=10
10.2-執行構造代碼塊
10.3-執行構造函數
11.執行Child的構造函數
11.1-初始化非類變量x=10
11.2-執行構造代碼塊
11.3-執行構造函數
12.執行Child對象demo.function方法
13.再次實例化Child,其父類Parent已經加載過了。Child也加載過了。
14.先執行父類構造方法
14.1-初始化非類變量a=10
14.2-執行構造代碼塊
14.3-執行構造函數
15.執行Child構造函數
15.1-初始化非類變量x=10
15.2-執行構造代碼塊
15.3-執行構造函數
16.執行Child對象child.function方法