《Effective Java》被譽為 Java 程序員的「必讀經典」,地位等同《Effective C++》。本系列筆記記錄核心條目精華,助力進階。第一章聚焦對象生命週期管理。
範例: Boolean.valueOf(boolean) 返回預緩存 Boolean.TRUE/FALSE,不創建新對象。
優點:
BigInteger.probablePrime 比構造器語義清晰;多構造器參數順序易混淆時尤佳。Collections 靜態工廠返回 20 多種 Collection 實現,API 隱藏具體類。缺點:
valueOf/of/getInstance/newInstance/getType。建議: 無強烈理由優先用構造器;需控制實例數量、返回子類型、語義化時用靜態工廠。
兩種寫法:
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
}
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public static Elvis getInstance() { return INSTANCE; }
}
序列化陷阱: 僅實現 Serializable 不夠,反序列化會產生新實例。必須提供 readResolve:
private Object readResolve() { return INSTANCE; }
工具類(如 java.util.Arrays、Collections)不應被實例化。抽象類無效(可被子類實例化)。唯一解法:顯式私有構造器:
public class UtilityClass {
private UtilityClass() { throw new AssertionError(); } // 防止反射調用
public static void doSomething() { ... }
}
副作用:也禁止了繼承(子類無法調用 super())。
String s = "denny" 而非 new String("denny")。Pattern、DateFormat 等重量級對象聲明為 private static final,在靜態塊初始化。Long sum = 0L; for(...) sum += i; 每次創建 Long,改用 long 基本類型。內存洩漏在 Java 也存在。經典棧實現:
public Object pop() {
if (size == 0) throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // 關鍵:消除過期引用
return result;
}
其他洩漏源:緩存(需 WeakHashMap 或定時清理)、監聽器/回調未移除、ThreadLocal 未清理。工具:JProfiler、VisualVM、MAT 分析堆轉儲。
正確做法:顯式終止方法 + try-finally
InputStream in = new FileInputStream(file);
try { ... } finally { in.close(); } // 或 Java 7 try-with-resources
finalize 合理用途:
close() 時最後嘗試釋放非關鍵資源。