一、代碼塊和構造函數的初始化順序
先從實例代碼開始
父類
public class SuperClass {
static {
System.out.println("super static block init");
}
{
System.out.println("no static block init");
}
public SuperClass() {
System.out.println("super Instance");
}
子類
public class SubClass extends SuperClass {
static {
System.out.println("sub static block init");
}
{
System.out.println("sub no static block init");
}
public SubClass() {
System.out.println("sub Instance");
}
}
下面這行代碼的數據結果是什麼?
SuperClass superClass = new SuperClass();
輸出結果
super static block init
no static block init
super Instance
總結:針對單個類,初始化順序:靜態代碼塊,非靜態代碼塊,構造函數
下面的這行代碼又會輸出怎麼樣的結果?
SubClass subClass = new SubClass();
輸出結果
super static block init
sub static block init
no static block init
super Instance
sub no static block init
sub Instance
子類實例化時,輸出的順序如下:
父類的靜態代碼塊->子類的靜態代碼塊->父類的非靜態代碼塊->父類的構造函數->子類的非靜態代碼塊->子類的構造函數
二、代用靜態方法和靜態變量
下面的示例代碼分析
父類
public class SuperClass {
static {
System.out.println("super static block init");
}
{
System.out.println("no static block init");
}
public SuperClass() {
System.out.println("super Instance");
}
public static void superTest() {
System.out.println("super method");
}
public static final Integer countInteger = 123;
public static final int countInt = 345;
}
子類
public class SubClass extends SuperClass {
static {
System.out.println("sub static block init");
}
{
System.out.println("sub no static block init");
}
public SubClass() {
System.out.println("sub Instance");
}
public static void sub() {
System.out.println("sub method");
}
public static final String hello = "hello";
public static final int testInt = 3;
public static final Integer testInteger = 4;
}
觀察輸出結果:
System.out.println(SuperClass.countInt);
//345
********************
System.out.println(SuperClass.countInteger);
// super static block init
// 123
********************
System.out.println(SubClass.countInteger);
// super static block init
// 123
********************
System.out.println(SubClass.countInt);
// 345
********************
SuperClass.superTest();
// super static block init
// super method
********************
SubClass.superTest();
// super static block init
// super method
********************
System.out.println(SubClass.testInt);
// 3
********************
System.out.println(SubClass.testInteger);
// super static block init
// sub static block init
// 4
********************
System.out.println(SubClass.hello);
// hello
********************
SubClass.sub();
// super static block init
// sub static block init
// sub method
********************
SubClass[] subClasses = new SubClass[2];//無任何內容輸出
總結
- 子類調用父類的靜態字段或者靜態方法,只會觸發父類的初始化;
- 父類調用父類的靜態方法,會觸發父類的靜態塊初始化;
- 子類調用子類的靜態方法,會觸發父類的靜態塊和子類的靜態塊的初始化;
- 關於Int,string 和Integer輸出結果的不同,是由於Int和string類型在編譯階段jvm放到了常量池中。