首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

《Java 編程思想》第 6 章:初始化與清理完整筆記 (構建器、重載、this、static、finalize、垃圾回收、陣列)

     編輯:Java 綜合教學

前言

本文整理自《Java 編程思想》(Thinking in Java) 第 4 版第 6 章,涵蓋構建器、方法重載、this/static、清理機制 (finalize/GC)、成員/陣列初始化細節與最佳實踐。

一、構建器:自動初始化的保證

  • 名稱必須與類名相同,無返回類型 (連 void 也不能寫)。
  • new ClassName() 觸發:分配記憶體 → 零值初始化 → 執行構建器代碼。
  • 若類無任何構建器,編譯器自動合成無參預設構建器;一旦自定義任意構建器,預設構建器消失。
class Rock {
    Rock() { System.out.println("Creating Rock"); }
    Rock(int i) { System.out.println("Rock number " + i); }
}
public class Test { public static void main(String[] args) { for (int i=0;i<10;i++) new Rock(i); } }

二、方法重載

  • 同名方法,參數列表不同 (類型、個數、順序)。
  • 返回類型不能作為重載依據:呼叫時可忽略返回值 (f();),編譯器無法判斷選哪個。
  • 構建器必須靠重載支援多種建構方式。
class Tree {
    int height;
    Tree() { prt("Planting seedling"); height = 0; }
    Tree(int h) { prt("Creating tree " + h); height = h; }
    void info() { prt("Tree is " + height); }
    void info(String s) { prt(s + ": " + height); } // 重載
    static void prt(String s) { System.out.println(s); }
}

三、this 關鍵字

用法說明範例
隱含參考非靜態方法內隱含第一參數banana.f(a,1) 實為 Banana.f(banana, a, 1)
引用當前對象返回 this 實現鏈式調用return this; → obj.inc().inc().print()
區分同名欄位/參數this.field = field;構建器/Setter 常見
構建器間調用必須為構建器第一行this("hi", 47); 僅能調用一個
class Flower {
    int petalCount = 0; String s = "null";
    Flower(int petals) { petalCount = petals; }
    Flower(String s) { this.s = s; }
    Flower(String s, int petals) { this(petals); this.s = s; } // 調用另一構建器
    Flower() { this("hi", 47); }
}

四、static 含義

  • 屬於類,不屬於實例:無 this,不可直接訪問非靜態成員。
  • 靜態方法/欄位屬於類共享,類載入時初始化 (一次)。
  • 工具類、常數、單例、工廠方法常用 static。

五、清理:finalize() 與垃圾回收器 (GC)

1. 核心誤區

GC ≠ 解構子。C++ delete 確定性呼叫解構子;Java finalize() 不保證被呼叫、不保證呼叫時間、不保證執行順序。

2. finalize() 正確用途

  • 釋放非 Java 記憶體資源 (JNI 分配的 malloc、檔案控制代碼、原生圖形資源等)。
  • 透過 native 方法呼叫 free()/CloseHandle()。
  • 不可用於釋放 Java 物件記憶體 (GC 自動處理)。

3. GC 行為觀察範例

class Chair {
    static boolean gcrun = false, f = false;
    static int created = 0, finalized = 0;
    int i;
    Chair() { i = ++created; if (created == 47) System.out.println("Created 47"); }
    protected void finalize() {
        if (!gcrun) { gcrun = true; System.out.println("GC 開始, created=" + created); }
        if (i == 47) { System.out.println("Finalizing #47"); f = true; }
        finalized++; if (finalized >= created) System.out.println("All " + finalized + " finalized");
    }
}
public class Garbage {
    public static void main(String[] args) {
        if (args.length==0) { System.err.println("Usage: java Garbage before|after|none"); return; }
        while (!Chair.f) { new Chair(); new String("padding"); }
        System.out.println("Created=" + Chair.created + ", finalized=" + Chair.finalized);
        if ("before".equals(args[0])) { System.gc(); System.runFinalization(); }
        System.out.println("bye");
        if ("after".equals(args[0])) System.runFinalizersOnExit(true); // 已棄用
    }
}

關鍵點:System.gc() 僅建議 GC;System.runFinalization() 建議執行 finalize;runFinalizersOnExit 已棄用 (線程不安全)。

六、成員初始化順序

  1. 靜態欄位/靜態初始化塊:按代碼順序,類載入時執行 (一次)。
  2. 非靜態欄位/實例初始化塊:按代碼順序,每次 new 時執行,在構建器之前。
  3. 構建器:最後執行。
class Card {
    Tag t1 = new Tag(1); // 1. 非靜態欄位
    Card() { System.out.println("Card()"); t3 = new Tag(33); } // 3. 構建器
    Tag t2 = new Tag(2); // 1. 非靜態欄位
    void f() {}
    Tag t3 = new Tag(3); // 1. 非靜態欄位
}
class Table {
    static Bowl b1 = new Bowl(1); // 1. 靜態欄位
    Table() { System.out.println("Table()"); b2.f(1); } // 3. 構建器
    static Bowl b2 = new Bowl(2); // 1. 靜態欄位
}

輸出順序:Bowl(1) → Bowl(2) → Table() → f(1) → Bowl(4) → Bowl(5) → Bowl(3) → Cupboard() ...

七、顯式靜態/非靜態初始化塊

  • static { ... }:類載入時執行一次,可進行複雜靜態初始化邏輯。
  • { ... }:每次 new 執行,支援匿名內部類初始化。

八、陣列初始化完全指南

1. 定義語法

int[] a1;           // 引用變數,無陣列物件
int a2[];           // C 風格,同義
int[] a3 = {1,2,3}; // 靜態初始化 (編譯器推導長度)
int[] a4 = new int[5]; // 動態分配,元素自動零值
int[] a5 = new int[]{4,5,6}; // 匿名陣列建立

2. 陣列特性

  • length 唯讀屬性,越界拋 ArrayIndexOutOfBoundsException (安全)。
  • 引用賦值僅複製引用:a2 = a1 → 兩變數指向同一陣列物件。
  • 基本型別陣列元素自動初始化為 0/false/'\0';引用型別陣列元素為 null。

3. 多維陣列

int[][] m1 = {{1,2},{3,4}};           // 靜態
int[][] m2 = new int[2][3];           // 矩形
int[][] m3 = new int[3][]; m3[0]=new int[2]; m3[1]=new int[5]; // 齒狀陣列 (每行長度不同)
Integer[][] obj = {{new Integer(1),new Integer(2)}, {new Integer(3)}};

九、總結:安全初始化的鐵律

  1. 構建器確保對象創建即完整初始化 (編譯器強制)。
  2. 靜態初始化僅一次,延遲到類首次主動使用。
  3. finalize() 僅用於原生資源釋放,不可依賴其釋放 Java 記憶體。
  4. 陣列越界自動檢查,犧牲微小效能換取記憶體安全。
  5. 理解初始化順序 (靜態→非靜態→構建器) 避免前向引用錯誤。

這些機制共同構建了 Java「無非預期未初始化狀態」的安全基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved