java.util.prefs.Preferences 是 JDK 1.4 引入的跨平台持久化配置存儲機制,專為「用戶偏好設置」設計(如窗口位置、最近打開文件、主題選擇)。它不是通用配置文件替代品,而是針對用戶級/系統級簡鍵值存儲的標準化方案。
| 特性 | 說明 |
|---|---|
| 跨平台 | Windows: 註冊表; Linux/macOS: ~/.java/.userPrefs/ XML 文件 |
| 層級結構 | 節點樹狀結構,按包名隔離:/com/myapp/prefs |
| 類型安全 | 提供 get/put Boolean, Int, Long, Float, Double, String, Byte[] |
| 自動刷新 | 延遲寫入,JVM 關閉時自動持久化,可手動 flush() |
| 導入導出 | 支持 XML 導入導出,便於備份遷移 |
| 權限隔離 | 用戶節點 userRoot() vs 系統節點 systemRoot() (需管理員權限) |
// 用戶級節點 (推薦,無需權限)
Preferences userPrefs = Preferences.userNodeForPackage(MyClass.class);
// 或指定路徑
Preferences userPrefs = Preferences.userRoot().node("/com/myapp/settings");
// 系統級節點 (需管理員權限,慎用)
Preferences sysPrefs = Preferences.systemNodeForPackage(MyClass.class);
// 寫入
prefs.put("window.title", "My App");
prefs.putInt("window.width", 800);
prefs.putInt("window.height", 600);
prefs.putBoolean("auto.save", true);
prefs.putDouble("zoom.level", 1.5);
prefs.putByteArray("icon.data", iconBytes);
// 讀取 (帶默認值,鍵不存在不拋異常)
String title = prefs.get("window.title", "Default Title");
int width = prefs.getInt("window.width", 1024);
boolean autoSave = prefs.getBoolean("auto.save", false);
// 檢查鍵是否存在
if (prefs.keys().hasMoreElements()) { ... } // 遍歷所有鍵
// 刪除鍵
prefs.remove("obsolete.key");
// 刪除整個節點及子節點 (謹慎)
prefs.removeNode();
// 獲取子節點
Preferences child = prefs.node("subcategory");
// 導出 XML (備份/遷移)
try (OutputStream os = new FileOutputStream("prefs-backup.xml")) {
prefs.exportSubtree(os);
}
// 導入 XML
try (InputStream is = new FileInputStream("prefs-backup.xml")) {
Preferences.importPreferences(is);
}
public final class AppPreferences {
private static final Preferences PREFS = Preferences.userNodeForPackage(AppPreferences.class);
// 鍵常量定義
private static final String KEY_WINDOW_X = "window.x";
private static final String KEY_WINDOW_Y = "window.y";
private static final String KEY_WINDOW_WIDTH = "window.width";
private static final String KEY_WINDOW_HEIGHT = "window.height";
private static final String KEY_THEME = "theme";
private static final String KEY_RECENT_FILES = "recent.files";
// 默認值
private static final int DEFAULT_WIDTH = 800;
private static final int DEFAULT_HEIGHT = 600;
private AppPreferences() {}
// === 窗口幾何 ===
public static void saveWindowBounds(int x, int y, int width, int height) {
PREFS.putInt(KEY_WINDOW_X, x);
PREFS.putInt(KEY_WINDOW_Y, y);
PREFS.putInt(KEY_WINDOW_WIDTH, width);
PREFS.putInt(KEY_WINDOW_HEIGHT, height);
}
public static Rectangle getWindowBounds() {
return new Rectangle(
PREFS.getInt(KEY_WINDOW_X, 100),
PREFS.getInt(KEY_WINDOW_Y, 100),
PREFS.getInt(KEY_WINDOW_WIDTH, DEFAULT_WIDTH),
PREFS.getInt(KEY_WINDOW_HEIGHT, DEFAULT_HEIGHT)
);
}
// === 主題 ===
public static void setTheme(String themeName) {
PREFS.put(KEY_THEME, themeName);
}
public static String getTheme() {
return PREFS.get(KEY_THEME, "light");
}
// === 最近文件 (最多 10 個) ===
public static void addRecentFile(String filePath) {
String[] recent = getRecentFiles();
List<String> list = new ArrayList<>(Arrays.asList(recent));
list.remove(filePath); // 去重
list.add(0, filePath); // 置頂
if (list.size() > 10) list = list.subList(0, 10);
PREFS.put(KEY_RECENT_FILES, String.join("|", list));
}
public static String[] getRecentFiles() {
String data = PREFS.get(KEY_RECENT_FILES, "");
return data.isEmpty() ? new String[0] : data.split("\\|");
}
// === 強制刷新 (關鍵操作後調用) ===
public static void flush() {
try { PREFS.flush(); } catch (BackingStoreException e) { log.error("刷新失敗", e); }
}
}
public class MainFrame extends JFrame {
public MainFrame() {
// 恢復窗口狀態
Rectangle bounds = AppPreferences.getWindowBounds();
setBounds(bounds);
setTheme(AppPreferences.getTheme());
// 關閉時保存
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
AppPreferences.saveWindowBounds(getX(), getY(), getWidth(), getHeight());
AppPreferences.flush();
}
});
}
}
| ✅ 適用 | ❌ 不適用 |
|---|---|
| 用戶界面偏好 (窗口、主題、字體) | 應用核心業務配置 (數據庫連接、API Key) |
| 最近使用列表 (文件、項目、搜索歷史) | 複雜結構化數據 (列表、對象圖) |
| 輕量級鍵值持久化 | 高併發寫入、事務性要求 |
| 跨平台桌面應用 | 服務端部署 (容器化環境註冊表/文件系統不可靠) |
服務端/雲原生環境建議遷移至:
HKEY_CURRENT_USER\Software\JavaSoft\Prefs\com\myapp~/.java/.userPrefs/com/myapp/prefs.xml