Effective Java Item 62:避免使用strings,因為其他類型更適合
整理 Effective Java 書中 Item 62: Avoid using strings when other types are more appropriate 心得筆記
主旨
String 很好用,但也很容易被濫用。因為輸入資料常常是文字格式,很多人會直接用 String 當作萬用資料型別──
但這會造成型別不清、錯誤率高、效能差,也難以維護。
本篇重點就是:不要把 String 當萬用型別。若有更合適的型別,就該使用更合適的型別。
點出問題:三種常見錯誤用法
1. 拿 String 當作其他值型別(primitive、boolean)
錯誤示範:
String age = "18"; //不應該用 String 存數字
String isActive = "true"; // 用來表示布林值也不對
正確做法:
int age = 18;
boolean isActive = true;
從外部系統輸入進來是文字沒錯,但轉型後才是正確的邏輯建模。
2. 拿 String 當 enum 用
String userRole = "ADMIN"; // 哪天拼錯就爆炸了
正確寫法應該是 enum:
enum Role { ADMIN, USER, GUEST }
Role userRole = Role.ADMIN;
這樣程式碼更安全、IDE 有提示、也能使用 switch。
3. 拿 String 表示複合資料(aggregate type)
錯誤示範:
String compoundKey = className + "#" + id; // 粗暴地把資料串起來
缺點:
- 要解析就得自己切字串
- 萬一資料中有
#會爆炸 - 沒有型別,容易誤用
正確作法:定義一個 class
class CompoundKey {
private final String className;
private final String id;
// 建構子、equals、hashCode、toString 自動產生
}
延伸情境:String 作為 capability(權限/資源鑰匙)
早期 ThreadLocal API 的錯誤設計:
ThreadLocal.set("myKey", value);
ThreadLocal.get("myKey");
問題:
- 所有 key 是全域共用,可能被人亂用或重複
- 無法保障獨立性與安全性
改善方式 1:用不可偽造的物件當 key
ThreadLocal.Key myKey = ThreadLocal.getKey();
ThreadLocal.set(myKey, value);
改善方式 2:直接讓 key 本身就是變數
ThreadLocal<String> myLocal = new ThreadLocal<>();
myLocal.set("hello");
String result = myLocal.get();
這就是現在 Java 提供的 java.lang.ThreadLocal<T> 實作。
不只安全,也具備型別檢查,完全不需要硬記 key 字串。
小結:String 不是萬用型別
何時該避免使用 String?
| 情境 | 正確型別 |
|---|---|
| 儲存數值、布林值等基本資料 | int, float, boolean 等 |
| 有固定選項的狀態值 | enum |
| 多個欄位的複合資料 | class 結構體 |
| 權限、識別符、資源 key | 專屬物件或封裝型別 |
結論:別再把
String當作資料的萬用型別。程式邏輯更清晰、錯誤更少、效能更好。
Read other posts