本文整理自《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); }
}
| 用法 | 說明 | 範例 |
|---|---|---|
| 隱含參考 | 非靜態方法內隱含第一參數 | 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); }
}
this,不可直接訪問非靜態成員。static。GC ≠ 解構子。C++
delete確定性呼叫解構子;Javafinalize()不保證被呼叫、不保證呼叫時間、不保證執行順序。
malloc、檔案控制代碼、原生圖形資源等)。native 方法呼叫 free()/CloseHandle()。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 已棄用 (線程不安全)。
new 時執行,在構建器之前。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 執行,支援匿名內部類初始化。int[] a1; // 引用變數,無陣列物件
int a2[]; // C 風格,同義
int[] a3 = {1,2,3}; // 靜態初始化 (編譯器推導長度)
int[] a4 = new int[5]; // 動態分配,元素自動零值
int[] a5 = new int[]{4,5,6}; // 匿名陣列建立
length 唯讀屬性,越界拋 ArrayIndexOutOfBoundsException (安全)。a2 = a1 → 兩變數指向同一陣列物件。false/'\0';引用型別陣列元素為 null。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)}};
finalize() 僅用於原生資源釋放,不可依賴其釋放 Java 記憶體。這些機制共同構建了 Java「無非預期未初始化狀態」的安全基石。