創建子類對象時,父類構造器總先於子類構造器執行。若父類無無參構造器,子類必須在構造器首行顯式調用 super(參數) 指定父類構造器,否則編譯失敗。
// 方案1:父類添加無參構造器
class Super { Super() {} }
// 方案2:子類顯式調用 super(str)
class Sub extends Super {
Sub(String str) { super(str); /* ... */ }
}
方案 1 只輸出子類信息;方案 2 輸出父類再子類信息。本質區別在於是否執行父類初始化邏輯。
創建對象時,JVM 按以下順序執行:
class Two {
One one_1 = new One("one-1"); // 非靜態成員
static One one_3 = new One("one-3"); // 靜態成員
Two(String s) { System.out.println(s); }
}
public class Test {
static Two two_3 = new Two("two-3"); // 主類靜態成員
public static void main(String[] args) {
System.out.println("main start");
new Two("two-1");
new Two("two-2");
}
}
輸出順序:
one-3 // 類 Two 靜態成員(最先,僅一次)
one-1 // Two 非靜態成員
two-3 // Two 構造器(主類靜態成員初始化)
main start // main 方法
one-1 // 第二次 new Two
two-1
one-1 // 第三次 new Two
two-2
注意:one-3 只輸出一次,證明靜態成員僅在類首次主動使用時初始化一次。
不僅創建對象,以下操作也會觸發類初始化(執行靜態成員/塊):
Class.forName()this() 或 super()super()