必须用StandardCharsets.UTF_8而非"UTF-8"字符串,因其编译期校验、IDE可导航、实例唯一;US_ASCII限0x00–0x7f超范围静默替为?;ISO_8859_1非万能解码器,误用致乱码。

直接用 "UTF-8" 这类字符串作为编码参数,看着简单,实则埋着运行时崩溃、跨平台不一致、团队协作混乱三颗雷。用 StandardCharsets.UTF_8 替代,是 Java 7 起就该养成的硬性规范。
为什么字符串编码名容易出问题
手动写 "UTF-8" 是纯字符串,编译器完全不管它对不对:
- 拼成
"utf-8"、"UTF_8"或"UTF8",编译通过,运行时才抛UnsupportedEncodingException或IllegalArgumentException - Android 某些旧版本对大小写敏感,
"utf-8"可能触发非预期 fallback 行为 - 不同 JDK 实现或嵌入式环境,只认标准名称
"UTF-8",其他变体直接失败 -
Charset.forName("UTF-8")每次调用都查表+反射,有开销,且返回对象不一定 == 相等
StandardCharsets.UTF_8 的实际好处
它不是工具方法,而是一个 JVM 预加载、类型安全的静态常量:
- 编译期就校验:写错字段名(如
StandardCharsets.UTP_8)IDE 立刻报红,不等到运行 - 零异常负担:传入
new String(bytes, StandardCharsets.UTF_8)不会抛受检异常,不用包 try-catch - 实例唯一:所有地方用的都是同一个对象,
==和equals()都稳定可靠,适合缓存判断或配置比对 - IDE 可导航:Ctrl+点击直达源码,看清它是怎么初始化的,也方便查文档
必须导入才能用
StandardCharsets 不是 Charset 的内部类,也不是自动导入项。光写 import java.nio.charset.Charset; 没用:
- 必须显式添加:
import java.nio.charset.StandardCharsets; - 常见错误场景:用在
Scanner、Files.readAllLines()、InputStreamReader构造中,忘了这行导入就编译失败 - Android 开发注意:4.4+ 才完整支持全部常量,低版本需降级处理
ISO_8859_1等
别乱用的三个典型常量
不是所有 StandardCharsets.xxx 都能通用,得看场景:
-
StandardCharsets.UTF_8:正文、JSON、日志、用户数据首选;但 HTTP 头、URL 参数、POSIX 文件名等要求纯 ASCII 的地方不能直接用 -
StandardCharsets.US_ASCII:严格限定 0x00–0x7F;超范围字符(如中文、€、é)会被静默替换成?;适合协议头解析、安全路径生成 -
StandardCharsets.ISO_8859_1:单字节映射,仅覆盖 U+0000–U+00FF;它不是“万能兜底”,对 UTF-8 编码的中文只会显示为 Latin-1 乱码,不是还原











