properties.load() 读不到中文值是因为默认用 iso-8859-1 解码,需 java 8+ 用 inputstreamreader 指定 utf-8 或 java 9+ 直接传 charset;getproperty() 返回 null 多因 key 大小写、空格、bom 不匹配;类路径加载推荐 getresourceasstream(),绝对路径易失效;properties 非完全线程安全,多线程热更新建议用 concurrenthashmap。

Properties.load() 为什么读不到中文值?
默认用 ISO-8859-1 解码,遇到 UTF-8 编码的中文会变成乱码或问号。不是文件写错了,是加载时没指定编码。
- Java 8 及以上:改用
Properties.load(Reader),配合InputStreamReader指定UTF-8 - 示例:
try (InputStream is = getClass().getResourceAsStream("/config.properties"); Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { props.load(reader); } - Java 9+ 支持
Properties.load(InputStream, Charset),更直接 - 别用
FileInputStream直接传路径——类路径资源要用getResourceAsStream()
getProperty() 返回 null 的常见原因
不是配置写错了,大概率是 key 对不上:大小写、空格、BOM 或注释干扰都会导致匹配失败。
- key 严格区分大小写:
db.url和DB.URL是两个键 - 行首/行尾空格会被保留在 key 中(
props.getProperty("port ")≠"port") - 带 BOM 的 UTF-8 文件会让 key 开头多出
\uFEFF,肉眼不可见 - 用
props.stringPropertyNames()打印所有实际加载的 key,比盲猜靠谱
Properties 从 classpath 加载 vs 从绝对路径加载的区别
行为一致,但路径解析逻辑完全不同,出错表现也不同。
- 类路径加载(推荐):
getClass().getResourceAsStream("/config.properties")—— 走 classloader,可打包进 jar,路径以/开头表示根目录 - 绝对路径加载:
new FileInputStream("/etc/myapp/config.properties")—— 依赖文件系统,部署时容易路径失效 - 相对路径(如
"config.properties")是相对于 JVM 启动目录,不是源码目录,极难调试 - Spring Boot 用户注意:
Properties不自动识别application.properties的 profile 分区,那是 Spring 自己解析的
Properties 线程安全吗?并发读写要加锁吗?
不安全。虽然 getProperty() 是只读方法,但若另一线程正在调用 load() 或 put(),可能看到部分更新状态。
立即学习“Java免费学习笔记(深入)”;
-
Properties继承自Hashtable,本身方法是同步的,但组合操作(比如先getProperty再setProperty)不是原子的 - 多数场景下配置只加载一次,之后只读 —— 这种情况不用锁,但得确保加载完成后再发布给其他线程(可用
final字段 + 构造器初始化) - 如果真需要运行时热更新,建议用
ConcurrentHashMap<string string></string>替代,自己封装 load 逻辑 - 别依赖
Properties.list()做日志 —— 它不是线程安全的输出方法,可能抛ConcurrentModificationException










