在 Java 開發中,將字串轉換為布林值是常見操作。許多開發者直覺會使用 Boolean.getBoolean(String),但這個方法的行為往往不符合預期,導致難以發現的 Bug。本文深入剖析 Boolean.getBoolean 與 Boolean.parseBoolean 的本質差異,並提供正確的轉換最佳實踐。
String s1 = "false";
String s2 = "true";
String s3 = "fAlSe";
String s4 = "TrUe";
String s5 = "true_a";
// 使用 getBoolean
Boolean.getBoolean(s1); // false
Boolean.getBoolean(s2); // false <-- 不是 true!
Boolean.getBoolean(s3); // false
Boolean.getBoolean(s4); // false
Boolean.getBoolean(s5); // false
結果全部是 false,這明顯違反直覺。原因在於 getBoolean 並非用於字串解析,而是讀取系統屬性。
「當且僅當以參數命名的系統屬性存在,且等於 "true"(不區分大小寫)時,回傳 true。若無此屬性、屬性為空或 null,則回傳 false。」
關鍵點:它讀取的是 System.getProperty(name),而非解析傳入的字串內容!
// 正確用法:啟動時設定 -Dmy.flag=true
System.setProperty("my.flag", "true");
Boolean.getBoolean("my.flag"); // true
// 錯誤用法:直接傳字串值
Boolean.getBoolean("true"); // false(除非系統有名為 "true" 的屬性且值為 "true")
「將字串參數解析為 boolean 值。若字串不為 null 且忽略大小寫等於 "true",回傳 true;否則回傳 false。」
這才是我們要找的字串解析方法!
Boolean.parseBoolean("false"); // false
Boolean.parseBoolean("true"); // true
Boolean.parseBoolean("fAlSe"); // false
Boolean.parseBoolean("TrUe"); // true
Boolean.parseBoolean("true_a"); // false
Boolean.parseBoolean("yes"); // false
Boolean.parseBoolean(null); // false
| 特性 | Boolean.getBoolean(String) | Boolean.parseBoolean(String) |
|---|---|---|
| 用途 | 讀取 JVM 系統屬性 | 解析字串字面值 |
| 參數含義 | 屬性名稱 (key) | 要解析的字串值 |
| 大小寫敏感度 | 不區分 (比對值時) | 不區分 |
| null 處理 | 回傳 false | 回傳 false |
| 典型使用場景 | 啟動參數 -Dflag=true、配置開關 | 解析使用者輸入、設定檔、API 回應、表單資料 |
| 效能 | 涉及系統屬性查找,較慢 | 純字串比較,極快 |
public boolean toBoolean(String str) {
return Boolean.parseBoolean(str);
}
public Boolean toBooleanStrict(String str) {
if (str == null) return null;
String lower = str.trim().toLowerCase();
if ("true".equals(lower)) return true;
if ("false".equals(lower)) return false;
throw new IllegalArgumentException("無效的布林值: " + str);
}
public boolean toBooleanFlexible(String str) {
if (str == null) return false;
String lower = str.trim().toLowerCase();
return switch (lower) {
case "true", "yes", "y", "1", "on", "enable", "enabled" -> true;
case "false", "no", "n", "0", "off", "disable", "disabled" -> false;
default -> false; // 或拋出異常
};
}
public boolean toBooleanFromObject(Object obj) {
if (obj == null) return false;
if (obj instanceof Boolean b) return b;
if (obj instanceof String s) return Boolean.parseBoolean(s);
if (obj instanceof Number n) return n.intValue() != 0;
return false; // 其他類型視為 false
}
// ❌ 錯誤:props.getProperty 回傳字串 "true",但 getBoolean 當成屬性名
boolean enabled = Boolean.getBoolean(config.getProperty("feature.enabled"));
// ✅ 正確:使用 parseBoolean 解析字串值
boolean enabled = Boolean.parseBoolean(config.getProperty("feature.enabled"));
// 更佳:Apache Commons Configuration 或 Spring @Value 自動轉型
// ❌ request.getParameter 回傳 "true" 字串
boolean isAdmin = Boolean.getBoolean(request.getParameter("admin"));
// ✅ 正確
boolean isAdmin = Boolean.parseBoolean(request.getParameter("admin"));
// JSON: {"active": "true"} 字串而非布林
String activeStr = json.getString("active");
// ❌
boolean active = Boolean.getBoolean(activeStr);
// ✅
boolean active = Boolean.parseBoolean(activeStr);
若專案大量轉換,建議封裝工具類:
public final class BooleanUtils {
private BooleanUtils() {}
public static boolean parse(String str) {
return Boolean.parseBoolean(str);
}
public static Boolean parseOrNull(String str) {
if (str == null) return null;
String lower = str.trim().toLowerCase();
if ("true".equals(lower)) return true;
if ("false".equals(lower)) return false;
return null; // 無法識別
}
public static boolean parseWithDefault(String str, boolean defaultValue) {
Boolean result = parseOrNull(str);
return result != null ? result : defaultValue;
}
}
-D 啟動參數或 System.setProperty 設定的系統屬性開關。parseBoolean。BooleanUtils.toBoolean。口訣:
「getBoolean 讀系統屬性,parseBoolean 解字串值。
配置檔、請求參數、JSON 字串,統統用 parseBoolean 不會錯!」