编码和解码必须使用同一字符集且显式指定,不可依赖系统默认值;推荐用StandardCharsets.UTF_8进行getBytes()和new String()操作,确保跨平台一致性。

核心就一条:编码和解码必须用同一个字符集,且不能依赖系统默认值。
明确指定字符集,别让平台替你决定
Java 中 String.getBytes() 和 new String(byte[]) 都有重载方法支持传入 Charset。Windows 默认用 GBK,Linux/macOS 默认用 UTF-8,一旦跨平台传输又没显式指定,字节数组就会被错误解读。
- ✅ 推荐写法:
str.getBytes(StandardCharsets.UTF_8)和new String(bytes, StandardCharsets.UTF_8)—— 类型安全、不抛检查异常 - ✅ 可接受写法:
str.getBytes("UTF-8")—— 字符串名称要标准大写,小写如 "utf8" 或 "Utf-8" 可能失败 - ❌ 避免写法:
str.getBytes()(平台相关)、Charset.forName("UTF-8")(多一层异常风险)
两端约定一致,单边正确没用
只在发送端编码成 UTF-8 不够,接收端也必须用 UTF-8 解码。常见场景需同步检查:
- HTTP 传输:客户端 POST 前 encode 为 UTF-8,服务端读取时显式按 UTF-8 decode;响应头加
Content-Type: text/plain; charset=UTF-8 - 文件读写:写入时
str.getBytes(UTF_8),读取后立即用new String(bytes, UTF_8)还原 - 数据库操作:JDBC URL 加参数
useUnicode=true&characterEncoding=UTF-8,字段本身也设为 utf8mb4
快速验证与调试技巧
遇到乱码别猜,先看字节再比对:
- 打印编码结果:
System.out.println(Arrays.toString(str.getBytes(StandardCharsets.UTF_8)));看前几个字节是否符合 UTF-8 规律(中文通常以e4e5开头) - 查当前默认值:
System.out.println(Charset.defaultCharset());仅用于排查,不能用于业务逻辑 - 反向验证乱码:若收到一串疑似乱码的字符串,尝试用不同编码重新 decode —— 比如
brokenStr.getBytes(StandardCharsets.ISO_8859_1).decode(StandardCharsets.GBK),可能还原原始中文
只要全程使用同一标准字符集(推荐 UTF-8),并在编码、传输、解码每个环节都显式声明,跨系统变量乱码问题就能稳定解决。

















