java.util.Properties 繼承自 Hashtable,是處理鍵值對配置檔的標準工具。支援 .properties 文字格式與 .xml 格式雙向轉換。本文涵蓋核心 API、遍歷方式、XML 操作、編碼陷阱與生產環境最佳實務。
| 方法 | 說明 |
|---|---|
load(InputStream) | 從位元組流載入 (ISO-8859-1 編碼) |
load(Reader) | 從字元流載入 (可指定 UTF-8 等編碼) **推薦** |
store(OutputStream, comments) | 儲存為 .properties (ISO-8859-1) |
store(Writer, comments) | 儲存為 .properties (可指定編碼) **推薦** |
loadFromXML(InputStream) | 從 XML 載入 |
storeToXML(OutputStream, comment) | 儲存為 XML (UTF-8) |
getProperty(key) / getProperty(key, default) | 取值 (預設值版本避免 null) |
setProperty(key, value) | 設值 (同步更新內部 Hashtable) |
stringPropertyNames() | 取得所有鍵 (Set<String>,安全遍歷) |
Properties props = new Properties();
try (InputStream is = MyClass.class.getResourceAsStream("/config/app.properties")) {
if (is == null) throw new IllegalStateException("Config not found");
props.load(is); // 注意:預設 ISO-8859-1,中文會變亂碼
} catch (IOException e) {
throw new RuntimeException("Load config failed", e);
}
try (Reader reader = new InputStreamReader(
MyClass.class.getResourceAsStream("/config/app.properties"), StandardCharsets.UTF_8)) {
props.load(reader);
}
// 方式一:keySet (舊式,需轉型)
for (Object keyObj : props.keySet()) {
String key = (String) keyObj;
String value = props.getProperty(key);
System.out.println(key + "=" + value);
}
// 方式二:stringPropertyNames (推薦,型別安全)
for (String key : props.stringPropertyNames()) {
System.out.println(key + "=" + props.getProperty(key));
}
// 方式三:entrySet (需轉型)
for (Entry
if (props.containsKey("database.url")) { ... }
// 或
String url = props.getProperty("database.url", "jdbc:mysql://localhost:3306/default");
props.setProperty("app.version", "2.1.0");
props.setProperty("feature.new", "enabled");
try (Writer writer = new OutputStreamWriter(
new FileOutputStream("config/app.properties"), StandardCharsets.UTF_8)) {
props.store(writer, "Updated by deploy script at " + Instant.now());
}
// 存為 XML (自動 UTF-8)
try (OutputStream os = new FileOutputStream("config/app.xml")) {
props.storeToXML(os, "Application Configuration");
}
// 從 XML 載入
Properties propsXml = new Properties();
try (InputStream is = new FileInputStream("config/app.xml")) {
propsXml.loadFromXML(is);
}
| 實務 | 理由 | 做法 |
|---|---|---|
| **統一 UTF-8** | 避免中文亂碼、跨平台一致 | 永遠用 Reader/Writer + StandardCharsets.UTF_8 |
| **啟動時載入、快取單例** | 避免重複 I/O、確保一致性 | Spring @PropertySource / 靜態單例 / 配置中心 |
| **敏感資訊不入倉** | 密碼、金鑰洩露風險 | 用環境變數、Vault、K8s Secret 注入,Properties 僅存非敏感配置 |
| **提供預設值** | 避免 NullPointerException | getProperty(key, defaultVal) |
| **類型轉換封裝** | Properties 只存字串 | 自訂 Config.getInt(), getBoolean(), getDuration() |
| **熱重載 (可選)** | 不重啟更新配置 | 監聽檔案變更 (WatchService) 或 Spring Cloud Config / Apollo |
load(InputStream) 固定 ISO-8859-1 → 中文變 ??? 或亂碼。store(OutputStream) 會將非 ASCII 字元轉為 Unicode 轉義 \uXXXX,人類難讀。Properties 非執行緒安全 (繼承 Hashtable 雖同步但複合操作不原子)。store/load 自動處理。現代替代方案:Spring Boot
@ConfigurationProperties、Typesafe Config (HOCON)、YAML + SnakeYAML、Apollo/Nacos 配置中心。但Properties作為 JDK 零依賴基礎設施,理解其機制仍是必修課。