Properties遍历会漏掉父级配置,应使用propertyNames()而非keys();getProperty()只返回String值,非String值需用get();加载时需指定UTF-8编码避免中文乱码;Hashtable同步不保证组合操作线程安全。

Properties遍历会漏掉父级配置?用propertyNames()而不是keys()
Java的Properties支持层级继承(通过setParent()或构造时传入),但很多人直接调用keys()或转成entrySet(),结果只拿到当前实例里的键,父级里定义的配置全丢了。
根本原因是keys()和entrySet()都来自Hashtable,不感知Properties自己维护的父子关系;而propertyNames()才是专为这个场景设计的——它会递归向上收集所有可访问的key。
- 用
propertyNames()返回Enumeration<string></string>,安全遍历全部有效属性名 - 别用
keys()(返回Enumeration<object></object>)或stringPropertyNames()(它跳过非String值,且不查父级) - 如果必须用增强for循环,先转成
List:List<String> allKeys = Collections.list(props.propertyNames());
为什么getProperty("key")有时返回null,但get("key")能取到?类型擦除+默认值陷阱
Properties是Hashtable<object object></object>的子类,但对外暴露的getProperty()方法只认String类型的value,并在找不到时返回null或你传的默认值;而get()走的是父类逻辑,可能返回原始Object(比如Integer、Boolean),甚至是你手动put("key", 123)塞进去的非字符串值。
- 配置文件加载进来的值一定是
String,所以getProperty()最安全 - 如果你用
put()往Properties里塞了非String值,getProperty()永远返回null(它内部做了instanceof String检查) - 写工具类封装读取逻辑时,优先用
getProperty(key, defaultValue),避免空指针
加载properties文件时中文乱码?别硬扛load(InputStream)
JDK 8及之前,load(InputStream)强制按ISO-8859-1解析,中文直接变问号;JDK 9+虽加了load(Reader),但没人会记得改——尤其当项目还在用老Spring或老旧构建脚本时。
立即学习“Java免费学习笔记(深入)”;
- 统一用
load(Reader),配合InputStreamReader指定UTF-8:props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
- 如果必须用
load(InputStream)(比如对接旧API),提前把文件内容转义:中文写成\u4f60\u597d格式,load()才能正确还原 - Maven资源过滤开启后,
src/main/resources下properties文件默认按平台编码处理,建议显式配置encoding插件参数
并发修改Properties对象危险吗?Hashtable不是线程安全的“完全体”
Hashtable的方法确实加了synchronized,但Properties常见操作如“先getProperty再setProperty”是两步,中间可能被其他线程插入修改——这不是锁粒度问题,是业务逻辑原子性缺失。
- 单次
setProperty()或getProperty()是线程安全的,但组合操作不是 - 不要依赖
Hashtable的同步来保护整个配置生命周期,尤其在Spring等容器里被多处引用时 - 如果需要运行时动态更新配置,考虑用
ConcurrentHashMap<string string></string>替代,或加一层读写锁包装
父子继承、类型判断、字符编码、并发边界——这四个点卡住的人最多,而且往往报错信息根本不提这些关键词。


















