Java靜態程式碼塊和類初始化、例項初始化過程
1. 靜態程式碼塊
靜態程式碼塊:定義在類中方法外,使用static修飾
①可以為類變數(靜態變數)初始化
②靜態程式碼塊在第一次使用這個類之前執行,即在類初始化時執行,且只執行一次
③若有多個靜態程式碼塊,那麼按照定義的先後順序依次執行
④在靜態程式碼塊中不能訪問非靜態成員(屬性、方法、內部類)
⑤在靜態程式碼塊中不能使用this和super關鍵字
⑥靜態程式碼塊的執行優先於main方法、非靜態程式碼塊和構造方法的執行
⑦父類靜態程式碼塊的執行優先於子類靜態程式碼塊執行
程式碼示例:
public class StaticBlockTest { public static void main(String[] args) { MyClass.show(); MyClass.show(); MyClass.show(); } static { System.out.println("StaticBlockTest類靜態程式碼塊"); } } class MyClass { static { System.out.println("MyClass類靜態程式碼塊1"); } public static void show() { System.out.println("MyClass類靜態方法"); } static { System.out.println("MyClass類靜態程式碼塊2"); } }
執行結果:
StaticBlockTest類靜態程式碼塊
MyClass類靜態程式碼塊1
MyClass類靜態程式碼塊2
MyClass類靜態方法
MyClass類靜態方法
MyClass類靜態方法
2. 類初始化
類初始化即執行類初始化方法:<clinit>()
類初始化方法,一個類只有一個。它也是由編譯器編譯生成的,由兩部分程式碼組成:
①靜態變數的顯式賦值程式碼
②靜態程式碼塊的程式碼
其中①和②是按定義的先後順序依次執行的
程式碼示例:
public class InitTest { public static void main(String[] args) { MyClass my = new MyClass(); } } class MyClass { static { System.out.println("MyClass類靜態程式碼塊1"); } private static String str = assingn(); public static void show() { System.out.println("MyClass類靜態方法"); } private static String assingn() { System.out.println("assign()方法為靜態變數顯式賦值"); return "java"; } static { System.out.println("MyClass類靜態程式碼塊2"); } }
執行結果:
MyClass類靜態程式碼塊1
assign()方法為靜態變數顯式賦值
MyClass類靜態程式碼塊2
3. 子類初始化
一個類初始化時會先檢查它的父類是否初始化,如果父類沒有初始化,那麼會先初始化父類
(1)父類的初始化
-
父類的靜態變數的顯式賦值
-
父類的靜態程式碼塊
(2)子類的初始化
-
父類的靜態變數的顯式賦值
-
父類的靜態程式碼塊
程式碼示例:
public class InitTest2 { public static void main(String[] args) { /*Father f = new Father(); System.out.println("--------分隔線---------");*/ Son s = new Son(); } } class Father{ private static String info = assign(); static{ System.out.println("父類的靜態程式碼塊"); } //靜態方法不能被重寫 public static String assign(){ System.out.println("父類assign()方法"); return "Father"; } } class Son extends Father{ private static String info = assign(); static{ System.out.println("子類的靜態程式碼塊"); } public static String assign(){ System.out.println("子類assign()方法"); return "Son"; } }
執行結果:
父類assign()方法
父類的靜態程式碼塊
子類assign()方法
子類的靜態程式碼塊
4. 類初始化和例項初始化結合
先執行類初始化,後執行例項初始化
程式碼示例:
public class InitTest3 {
public static void main(String[] args) {
Demo d = new Demo();
}
}
class Demo{
{
System.out.println("非靜態程式碼塊1");
}
static{
System.out.println("靜態程式碼塊1");
}
public Demo(){
System.out.println("無參構造");
}
private static String info = assignInfo();
private String msg = assignMsg();
static{
System.out.println("靜態程式碼塊2");
}
{
System.out.println("非靜態程式碼塊2");
}
public static String assignInfo(){
System.out.println("assignInfo()方法");
return "hello";
}
public String assignMsg(){
System.out.println("assignMsg()方法");
return "msg";
}
}
執行結果:
靜態程式碼塊1
assignInfo()方法
靜態程式碼塊2
非靜態程式碼塊1
assignMsg()方法
非靜態程式碼塊2
無參構造
5. 子類初始化和子類例項初始化結合
執行順序:①父類的類初始化 => ②子類的類初始化 => ③父類的例項初始化方法 => ④子類的例項初始化方法
public class InitTest4 {
public static void main(String[] args) {
//Father f = new Father();
Son s = new Son();
}
}
class Father {
{
System.out.println("父類非靜態程式碼塊1");
}
static {
System.out.println("父類靜態程式碼塊1");
}
private static String info = assignInfo();
private String msg = assignMsg();
public Father() {
System.out.println("父類無參構造");
}
static {
System.out.println("父類靜態程式碼塊2");
}
{
System.out.println("父類非靜態程式碼塊2");
}
public static String assignInfo() {
System.out.println("父類assignInfo()方法");
return "hello";
}
public String assignMsg() {
System.out.println("父類assignMsg()方法");
return "msg";
}
}
class Son extends Father {
{
System.out.println("子類非靜態程式碼塊1");
}
static {
System.out.println("子類靜態程式碼塊1");
}
private static String info = assignInfo();
private String msg = assignMsg();
public Son() {
System.out.println("子類無參構造");
}
static {
System.out.println("子類靜態程式碼塊2");
}
{
System.out.println("子類非靜態程式碼塊2");
}
public static String assignInfo() {
System.out.println("子類assignInfo()方法");
return "hello";
}
public String assignMsg() {
System.out.println("子類assignMsg()方法");
return "msg";
}
}
父類靜態程式碼塊1
父類assignInfo()方法
父類靜態程式碼塊2
子類靜態程式碼塊1
子類assignInfo()方法
子類靜態程式碼塊2
父類非靜態程式碼塊1
子類assignMsg()方法
父類非靜態程式碼塊2
父類無參構造
子類非靜態程式碼塊1
子類assignMsg()方法
子類非靜態程式碼塊2
子類無參構造