1. 程式人生 > 實用技巧 >Java靜態程式碼塊和類初始化、例項初始化過程

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
子類無參構造