靜態代碼塊、構造代碼塊、構造函數、普通代碼塊介紹

前言

複習下Java中的靜態代碼塊、構造代碼塊、構造函數、普通代碼塊

正文

概念介紹

1、靜態代碼塊

定義:在類中使用static關鍵字聲明的代碼塊。靜態塊用於初始化類,爲類的屬性初始化。每個靜態代碼塊只會執行一次。由於JVM在加載類時會執行靜態代碼塊,所以靜態代碼塊先於主方法執行。

注意點

  • 靜態代碼塊在類被加載的時候就運行了,而且只運行一次,並且優先於各種代碼塊以及構造函數。如果一個類中有多個靜態代碼塊,會按照書寫順序依次執行。
  • 靜態代碼塊不能存在任何方法體中。因爲非靜態普通方法是通過加載類,然後new出實例化對象,通過對象才能調用這個方法,而靜態代碼塊只需要加載類之後就能運行了。而對於靜態方法,在類加載的時候,靜態方法也已經加載了,但是我們必須要通過類名或者對象名才能訪問,也就是說靜態代碼塊是主動運行的,而靜態方法是被動運行的。
  • 靜態代碼塊不能直接訪問實例變量和實例方法

2、構造代碼塊

定義:直接在類中定義且沒有加static關鍵字的代碼塊稱爲構造代碼塊。構造代碼塊在創建對象時被調用,每次創建對象都會被調用,並且構造代碼塊的執行次序優先於類構造函數。如果存在多個構造代碼塊,執行順序由他們在代碼中出現的次序決定,先出現先執行。

3、普通代碼塊

普通代碼塊和構造代碼塊的區別是,構造代碼塊是在類中定義的,而普通代碼塊是在方法體中定義的。且普通代碼塊的執行順序和書寫順序一致。

4、構造函數

注意點

  • 構造函數的命名必須和類名完全相同。在java中普通函數可以和構造函數同名,但是必須帶有返回值;
  • 構造函數的功能主要用於在類的對象創建時定義初始化的狀態。它沒有返回值,也不能用void來修飾。
  • 構造函數不能被直接調用,必須通過new運算符在創建對象時纔會自動調用;而一般的方法是在程序執行到它的時候被調用的;
  • 當定義一個類的時候,通常情況下都會顯示該類的構造函數,並在函數中指定初始化的工作也可省略,不過Java編譯器會提供一個默認的構造函數,此默認構造函數是不帶參數的。

實例測試

CodeBlock類代碼如下:

/**
 * Copyright (C), 2015-2020
 * FileName: CodeBlock
 * Author:   niko
 * Date:     2020/6/23 11:08
 * Description: 測試各種代碼塊
 * History:
 * <author>          <time>          <version>
 * 逝不等琴生          11:08           1.0
 */
package com.nzc.codeblock;

public class CodeBlock {
    static {
        System.out.println("我是靜態代碼塊——靜態代碼塊在類被加載的時候就運行了,而且只運行一次,並且優先於各種代碼塊以及構造函數");
    }

    {
        System.out.println("我是構造代碼塊——優先於構造函數執行,每次創建一個對象都執行一次");
    }

    public CodeBlock() {
        System.out.println("我是構造函數——每創建一個對象就執行一次");
    }

    public void normalFunction() {
        System.out.println("我是非靜態方法中的代碼塊——被類對象調用時執行");
    }

    public static void staticFunction() {
        System.out.println("我是靜態方法中的代碼塊——被類調用時執行");
    }
}

測試類代碼如下:

/**
 * Copyright (C), 2015-2020
 * FileName: TestCodeBlock
 * Author:   niko
 * Date:     2020/6/23 11:14
 * Description:
 * History:
 * <author>          <time>          <version>
 * 逝不等琴生          11:14           1.0
 */
package com.nzc.test;

import com.nzc.codeblock.CodeBlock;

public class TestCodeBlock {
    public static void main(String[] args) {
        new CodeBlock().normalFunction();
        new CodeBlock().normalFunction();
        System.out.println("=============以下爲靜態方法調用==========");
        CodeBlock.staticFunction();
        CodeBlock.staticFunction();
    }
    //    測試結果:
//我是靜態代碼塊——靜態代碼塊在類被加載的時候就運行了,而且只運行一次,並且優先於各種代碼塊以及構造函數
//我是構造代碼塊——優先於構造函數執行,每次創建一個對象都執行一次
//我是構造函數——每創建一個對象就執行一次
//我是非靜態方法中的代碼塊——被類對象調用時執行
//我是構造代碼塊——優先於構造函數執行,每次創建一個對象都執行一次
//我是構造函數——每創建一個對象就執行一次
//我是非靜態方法中的代碼塊——被類對象調用時執行
//=============以下爲靜態方法調用==========
//我是靜態方法中的代碼塊——被類調用時執行
//我是靜態方法中的代碼塊——被類調用時執行
}

測試結果如下圖所示:

總結:

即執行順序: 靜態代碼塊>構造代碼塊>構造函數>普通代碼塊

父類和子類中代碼塊執行順序

實例如下:

父類

public class Father {
    static {
        System.out.println("我是父類靜態代碼塊");
    }

    {
        System.out.println("我是父類構造代碼塊");
    }

    public Father() {
        System.out.println("我是父類構造函數");
    }

}

子類

public class Son extends Father {
    static {
        System.out.println("我是子類靜態代碼塊");
    }

    {
        System.out.println("我是子類構造代碼塊");
    }

    public Son() {
        System.out.println("我是子類構造函數");
    }

}

測試類如下


public class Test {
    public static void main(String[] args) {
        Son son1 = new Son();
        System.out.println("===================");
        Son son2 = new Son();
    }

}

測試截圖:

總結:

靜態代碼塊內容先執行,隨後執行父類構造代碼塊和構造方法,接着執行子類構造代碼塊和構造方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章