整理 Effective Java 書中 Item 59: Know and use the libraries 心得筆記

主旨

身為 Java 工程師,我們常會遇到「這個功能應該很常見」的需求。這時,不要急著自己寫,先去查 Java 標準函式庫有沒有現成的。
多數情況下,它們不只功能完整,還考慮了邊界條件、效能、可移植性與可讀性,遠遠優於臨時寫出的版本。

點出問題

假設想產生 0 到 n 之間的隨機整數,有人會這樣寫:

static Random rnd = new Random();
static int random(int n) {
    return Math.abs(rnd.nextInt()) % n;
}

乍看沒問題,但這段程式碼潛藏三大錯誤:

  1. 分佈偏斜問題:若 n 不是 2 的次方,模運算結果不是均勻分佈。
  2. 重複週期短:當 n 是 2 的次方,生成數可能很快重複。
  3. 可能產生負數Math.abs(Integer.MIN_VALUE) 仍是負數,導致 % n 變成負值,破壞正整數假設。
// 你以為會接近 50 萬,實際上可能印出 66 萬
int low = 0;
for (int i = 0; i < 1_000_000; i++) {
    if (random(n) < n / 2) low++;
}
System.out.println(low);

這些問題都會影響程式行為,而且有些錯誤非常難偵測。

劃重點:用對的函式庫

Java 標準函式庫早就幫你寫好了正確又高效的實作:

ThreadLocalRandom.current().nextInt(n);  // 推薦用法

或:

new Random().nextInt(n);  // 還是比自己寫好

從 Java 7 開始,ThreadLocalRandom 是大多數場景下的首選,它效能更高,執行緒安全。

✅ 結論:用 Random.nextInt(n)ThreadLocalRandom.current().nextInt(n),不要自己亂寫

函式庫的五大優勢

  1. 正確性更高
    寫函式庫的是演算法專家,經過多輪審查與實戰測試,使用他們寫的東西比你自己從頭寫更可靠。

  2. 省時間、省力氣
    可以把心力集中在解決業務問題,而不是處理底層細節。

  3. 效能持續優化
    標準函式庫會不斷被 JVM 團隊優化,免費享有更快的效能。

  4. 功能日益增加
    Java 每一版都新增實用 API,例如 Java 9 開始 InputStream.transferTo() 可直接輸出串流內容:

    try (InputStream in = new URL(args[0]).openStream()) {
        in.transferTo(System.out);
    }
    
  5. 提升可讀性與可維護性
    主流寫法大家都看得懂,也更容易交接、維護或整合。

真實世界案例:重新造輪子的反面教材

寫一個方法顯示網址內容,以前可能得這樣寫:

InputStream in = new URL(url).openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

但自從 Java 9,有了 transferTo(),整個寫法變成一行搞定,簡潔又不容易錯:

in.transferTo(System.out);

這就是「追蹤新功能、善用函式庫」的價值所在。

小結

用函式庫,不是不會寫,而是選擇聰明寫

實用提醒:

  • 每次 Java 釋出新版本,記得去看「新功能網頁」
  • 熟悉 java.lang, java.util, java.io 是基本功
  • 集合框架、streams、java.util.concurrent 是日常寫作的工具箱
  • 有特殊需求?考慮 Guava 等高品質第三方函式庫
  • 找不到才自己寫,但寫前請三思