2025-02-10

fancydeepin前言:這屬於 java 的基礎知識,你可以不瞭解,也可以不拿它當一回事,代碼也一樣能敲的順暢;這是很久之前,我從 C++ 轉 java 剛入門那會的看法,那會我堅持自己的理念:
    重實踐,講運用,輕理論。當然,對同一樣事物,在不同階段也會有不一樣的看法,這理念在某個時段已經不適合我,早就被拋棄瞭。不扯淡瞭,直接進入主題。

java 中的變量大致分為 成員變量 和 局部變量 兩大類。

成員變量:
    在類體裡面定義的變量稱為成員變量;
    如果該成員變量有 static 關鍵字修飾,則該成員變量稱為 靜態變量 或 類變量;
    如果該成員變量沒有 static 關鍵字修飾,則該成員變量被稱為 非靜態變量 或 實例變量。

局部變量:
    形參、方法內定義的變量、代碼塊中定義的變量,都屬於局部變量。

類變量 (靜態變量)
    1. 可以向前引用
    2. 變量屬於類本身
    3. 類變量不依賴類的實例,類變量隻在初始化時候在棧內存中被分配一次空間,無論類的實例被創建幾次,都不再為類變量分配空間
    4. 通過類的任意一個實例來訪問類變量,底層都將將其轉為通過類本身來訪問類變量,它們的效果是一樣的
    5. 一旦類變量的值被改變,通過類或類的任意一個實例來訪問類變量,得到的都將是被改變後的值
    6. 將在類的初始化之前初始化

實例變量(非靜態變量)
    1. 不能向前引用,如果向前引用,則稱為非法向前引用,這是不允許的
    2. 變量屬於類的實例對象
    3. 隨著類的實例被創建而分配內存空間

非靜態代碼塊
    直接由 { } 包起來的代碼,稱為非靜態代碼塊

靜態代碼塊
    直接由 static { } 包起來的代碼,稱為靜態代碼塊

類變量(靜態變量)、實例變量(非靜態變量)、靜態代碼塊、非靜態代碼塊 的初始化時機
    由 static 關鍵字修飾的(如:類變量[靜態變量]、靜態代碼塊)將在類被初始化創建實例對象之前被初始化,而且是按順序從上到下依次被執行;
    沒有 static 關鍵字修飾的(如:實例變量[非靜態變量]、非靜態代碼塊)初始化實際上是會被提取到類的構造器中被執行的,但是會比類構造器中的
    代碼塊優先執行到,其也是按順序從上到下依次被執行。

– 以上是本人在翻完 PDF 後的個人筆記和理解以及見解,不見得百分百對,以下附上本人測試示例代碼,會更有說服性

示例代碼

 1
 2/**
 3 * —————————————–
 4 * @文件: Statical.java
 5 * @作者: fancy
 6 * @郵箱: fancydeepin@yeah.net
 7 * @時間: 2012-7-9
 8 * @描述: TEST
 9 * —————————————–
10 */
11public class Statical {
12
13 /**
14     * 靜態代碼塊
15     * 類變量(靜態變量)可以向前引用(即:先引用,再定義)
16     */
17    static {
18        name = "fancydeepin"; // name 的定義在使用之後
19        System.out.println("—>  靜態代碼塊被執行   <—");
20    }
21 /**
22     * 類變量(靜態變量)在類的初始化之前初始化,無論類的實例將被創建多少個
23     * 類變量(靜態變量)都將隻在初始化時候在棧內存上分配一次空間
24     * 凡 static 修飾的,都將按位置被順序執行,所以,
25     * name 的值最終輸出 fancy 而不是上面的 fancydeepin
26     */
27    public static String name = "fancy"; //類變量(靜態變量)
28    private String mail = "myEmail"; //實例變量(非靜態變量),定義時指定初始值,會比在構造器賦予值更早執行
29   
30    public Statical() {
31        mail = www.aiwalls.com;
32        System.out.println("—> 構造器代碼塊被執行 <—");
33    }
34 /**
35     * 非靜態代碼塊
36     * 實際上,非靜態代碼塊在類初始化創建實例時,將會被提取到類的構造器中,
37     * 但是,非靜態代碼塊會比構造器中的代碼塊優先被執行
38     * 所以,mail 最終輸出的是類構造器中給定的值,也就是 www.aiwalls.com
39     * 而不是 www.aiwalls.com,更不是 myEmail
40     */
41    {
42        mail = "www.aiwalls.com";
43        System.out.println("—> 非靜態代碼塊被執行 <—");
44    }
45   
46    // getting and setting
47

測試類示例代碼

 1
 2      /**
 3         * 類變量(靜態變量)在類被初始化創建實例之前被初始化
 4         */
 5        System.out.println("—————–> @1 <—————-");
 6        System.out.println("name —>> " + Statical.name); // @1
 7        System.out.println("—————–> @1 <—————-");
 8       /**
 9         * 創建類的實例對象
10         */
11        System.out.println("—————–> @6 <—————-");
12        Statical statical = new Statical(); // @6
13        System.out.println("—————–> @6 <—————-");
14        /**
15         * 通過實例來訪問類變量,底層將轉化成通過類本身來訪問類變量
16         */
17        System.out.println("—————–> @2 <—————-");
18        System.out.println("name —>> " + statical.name); // @2
19        System.out.println("—————–> @2 <—————-");
20       /**
21         * 如果類變量的值被改變,再訪問類變量,將得到被改變後的值
22         */
23        Statical.name = "fancydeepin";
24       
25        System.out.println("—————–> @3 <—————-");
26        System.out.println("name —>> " + statical.name); // @3
27        System.out.println("—————–> @3 <—————-");
28       
29        System.out.println("—————–> @4 <—————-");
30        System.out.println("name —>> " + Statical.name); // @4
31        System.out.println("—————–> @4 <—————-");
32       /**
33         * 非靜態代碼塊 和 構造器 被執行的時機
34         */
35        System.out.println("—————–> @5 <—————-");
36        System.out.println("mail —>> " + statical.getMail()); // @5
37        System.out.println("—————–> @5 <—————-");
38

後臺輸出結果

—————–> @1 <—————-
—>  靜態代碼塊被執行   <—
name —>> fancy
—————–> @1 <—————-

—————–> @6 <—————-
—> 非靜態代碼塊被執行 <—
—> 構造器代碼塊被執行 <—
—————–> @6 <—————-

—————–> @2 <—————-
name —>> fancy
—————–> @2 <—————-

—————–> @3 <—————-
name —>> fancydeepin
—————–> @3 <—————-

—————–> @4 <—————-
name —>> fancydeepin
—————–> @4 <—————-

—————–> @5 <—————-
mail  —>> fancydeepin@yeah.net
—————–> @5 <—————-

 作者:fancydeepin

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *