傳統 Java 缺乏標準配置存儲位置:Properties 檔放哪?如何跨平台?JSR 10 引入 java.util.prefs 徹底解決:
HKEY_CURRENT_USER\Software\JavaSoft\Prefs)兩棵獨立樹:
// 非靜態方法:自動推導包名
Preferences userPrefs = Preferences.userNodeForPackage(this.getClass());
Preferences sysPrefs = Preferences.systemNodeForPackage(this.getClass());
// 靜態方法:手動指定絕對路徑
Preferences userPrefs = Preferences.userRoot().node("/com/myapp/config");
Preferences sysPrefs = Preferences.systemRoot().node("/com/myapp/config");
最佳實踐:以包名作為節點路徑前綴,避免命名衝突。
| 數據類型 | 寫入方法 | 讀取方法(需默認值) |
|---|---|---|
| String | put(key, value) | get(key, default) |
| boolean | putBoolean(key, value) | getBoolean(key, default) |
| int | putInt(key, value) | getInt(key, default) |
| long | putLong(key, value) | getLong(key, default) |
| float | putFloat(key, value) | getFloat(key, default) |
| double | putDouble(key, value) | getDouble(key, default) |
| byte[] | putByteArray(key, value) | getByteArray(key, default) |
限制:Key 長度 ≤ 80,Value 長度 ≤ 8192。底層統一轉為字串存儲。
異常:存儲不可用拋 BackingStoreException。
String[] keys = prefs.keys(); // 獲取所有鍵
prefs.remove(key); // 刪除單個鍵值
prefs.clear(); // 清空當前節點
prefs.removeNode(); // 刪除整個節點子樹
// 匯出單節點
prefs.exportNode(outputStream);
// 匯出整棵子樹
prefs.exportSubtree(outputStream);
// 匯入(靜態方法)
Preferences.importPreferences(inputStream);
格式:UTF-8 編碼 XML,適合版本控制、跨機器部署。
// 節點增減監聽
prefs.addNodeChangeListener(new NodeChangeListener() {
public void childAdded(NodeChangeEvent e) { ... }
public void childRemoved(NodeChangeEvent e) { ... }
});
// 鍵值變更監聽
prefs.addPreferenceChangeListener(new PreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent e) {
String key = e.getKey(), val = e.getNewValue();
// 熱加載配置、刷新 UI 等
}
});
符合 JavaBeans 事件模型,支援動態配置更新。
package net.zukowski.ibm;
import java.io.*; import java.util.prefs.*;
public class PrefsDemo {
public static void main(String[] args) {
String[] den = {"One","Two","Five","Ten","Twenty"};
String[] pic = {"Washington","Jefferson","Lincoln","Hamilton","Jackson"};
// 監聽器
NodeChangeListener ncl = new NodeChangeListener() {
public void childAdded(NodeChangeEvent e) {
System.out.println(e.getParent().name() + " added child " + e.getChild().name());
}
public void childRemoved(NodeChangeEvent e) {
System.out.println(e.getParent().name() + " removed child " + e.getChild().name());
}
};
PreferenceChangeListener pcl = new PreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent e) {
System.out.println(e.getNode().name() + " key=" + e.getKey() + " newVal=" + e.getNewValue());
}
};
Preferences prefs = Preferences.userRoot().node("/net/zukowski/ibm");
prefs.addNodeChangeListener(ncl);
prefs.addPreferenceChangeListener(pcl);
// 寫入
for (int i=0; i
注意:Preferences 不適合存儲大量業務數據、高併發寫入場景,請改用資料庫。