Java字符编码关键在一致与明确:URL需显式用UTF-8编码解码,Web请求须设request.setCharacterEncoding("UTF-8"),字节流操作应配对使用StandardCharsets.UTF_8,避免默认编码和重复解码。

Java 中字符编码与解码不是调用两个方法就完事的事,关键在“一致”和“明确”——编码用什么字符集,解码就必须用同一个;不指定,就等于把结果交给系统默认值,而它在不同环境可能完全不同。
URL 场景:用 URLEncoder / URLDecoder 必须带 UTF-8
URLEncoder.encode() 和 URLDecoder.decode() 都要显式传入 "UTF-8",绝不能用单参数老方法(已废弃)。
- 空格会变成 +,原始字符串里的加号 + 会被编码成 %2B,解码时自动还原,这点容易混淆
- 像
/ ? = &这类有语法意义的字符,如果出现在参数值里(比如搜索词包含“a/b”),也得编码,否则会破坏 URL 结构 - Web 开发中 request.getParameter() 会先按 ISO-8859-1 解一次码,再交给你。若前端传的是 UTF-8 编码的中文,你再用 UTF-8 解一次,就乱码了。解决办法是提前调用
request.setCharacterEncoding("UTF-8")
字节流场景:getBytes() 和 new String() 要配对使用
String 在内存中是 UTF-16,往外传必须转字节;收到字节后,也必须按原编码还原。
-
str.getBytes(StandardCharsets.UTF_8)是安全写法;避免用无参getBytes(),它依赖系统默认编码,不可靠 -
new String(bytes, StandardCharsets.UTF_8)才能正确还原;用错 charset(比如用 GBK 字节配 UTF-8 构造),结果就是一堆 或乱码 - 调试时可打印字节数组的十六进制,确认编码是否符合预期,例如 “你好” 的 UTF-8 是
E4 BD A0 E5 A5 BD
避免陷阱:别让容器或框架偷偷解码
Servlet 容器、Spring MVC、HTTP 客户端都可能在你不知情时做一次解码,导致重复解码或解码错层。
立即学习“Java免费学习笔记(深入)”;
- 查看原始请求串用
request.getQueryString(),它返回未处理的原始字符串,能帮你判断是否已被提前解码 - 前后端约定统一用 UTF-8,前端发送前 encodeURI 或 encodeURIComponent,后端只 decode 一次
- 复杂参数建议走 POST + JSON,绕过表单编码逻辑,由 Jackson 自动处理 UTF-8
查字符集支持:用 Charset.availableCharsets()
不是所有字符集在所有 JVM 上都可用,尤其在精简版或 Docker 环境中。
- 运行时检查:
Charset.isSupported("GBK")再使用,避免抛UnsupportedCharsetException - 推荐优先用
StandardCharsets.UTF_8(JDK 7+),类型安全、无需异常捕获、性能更好 - 不要硬写字符串如
"utf8",大小写和拼写错误(如 "utf-8" vs "UTF8")会导致异常


















