Java中字符编码与解码本质是“字符↔字节”双向转换:字符串内存恒用UTF-16(如“你”为U+4F60),对外交互须显式指定Charset;编码用String.getBytes(Charset),解码用new String(byte[], Charset),二者必须严格匹配,否则必然乱码。

Java 中字符编码和解码,本质是“字符 ↔ 字节”的双向转换过程。字符串在内存中始终以 UTF-16 形式存储(如 你 对应 Unicode 码点 U+4F60),但写入文件、发到网络、存进数据库时,必须转成字节;反过来,读取字节流后也必须按约定规则还原为可读字符串。关键不在“能不能做”,而在“用对同一套规则”——编码用 UTF-8,解码就必须用 UTF-8,否则大概率乱码。
编码:String → byte[]
把内存中的字符串变成字节序列,用于输出或传输:
- 推荐用 String.getBytes(Charset),显式指定编码,避免依赖系统默认值(不同环境可能不同)
- 例如:"你好".getBytes(StandardCharsets.UTF_8) 得到 6 字节(每个中文占 3 字节);用 "你好".getBytes("GBK") 则得 4 字节(每个中文占 2 字节)
- 慎用无参 getBytes():它调用平台默认编码(Windows 常是 GBK,Linux/macOS 多是 UTF-8),跨环境易出错
解码:byte[] → String
把接收到的字节序列还原为字符串,用于显示或处理:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 必须使用 new String(byte[], Charset) 构造函数,并传入与编码时完全一致的 Charset
- 比如用 UTF-8 编码的字节数组,不能用 new String(bytes, "GBK") 解码,否则出现 “”
- 注意:new String(byte[]) 无参构造同样依赖平台默认编码,应避免
URL 场景要单独处理
普通字符串编码不适用于 URL 参数,因为 URL 有特殊保留字符(如空格、&、/),需用专门机制:
立即学习“Java免费学习笔记(深入)”;
- 编码用 URLEncoder.encode(str, "UTF-8"):把空格变 +,中文变 %E4%B8%AD 这类格式
- 解码用 URLDecoder.decode(encodedStr, "UTF-8"):把 %E4%B8%AD 还原为 “中”
- 务必保证 encode 和 decode 使用相同字符集,且 URL 编码不是通用字符编码,不能混用 getBytes / new String
查编码、选编码的实用建议
开发中常需确认或切换编码方式:
- 查看当前 JVM 默认编码:Charset.defaultCharset().name()
- 列出所有支持的编码:Charset.availableCharsets().keySet()
- 优先选用 UTF-8:兼容英文、支持全球字符、跨平台稳定;GBK 仅建议在对接老旧 Windows 本地系统时使用
- 遇到乱码先反推:看字节原始值(如打印十六进制),再比对 UTF-8 / GBK 的典型字节模式,快速定位错在哪一环

















