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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM