直接写"UTF-8"易出错,因拼写、大小写、横线缺失(如"utf8")、下划线(如"UTF_8")或BOM处理差异,可能导致UnsupportedEncodingException或静默乱码;而StandardCharsets.UTF_8是JDK 7+提供的编译期校验、IDE可补全、无硬编码风险的Charset常量。

为什么直接写 "UTF-8" 容易出错
手写编码字符串看似简单,但实际运行时可能因拼写、大小写、空格或 BOM 处理差异引发 UnsupportedEncodingException 或静默乱码。比如 "utf8"(少横线)、"UTF_8"(下划线)在部分 JDK 版本中不被识别;Android 上某些旧版本甚至对 "UTF-8" 的解析更严格。而 StandardCharsets 是 JDK 7+ 提供的不可变常量类,所有字段都是 Charset 实例,编译期可校验、IDE 可自动补全、无字符串硬编码风险。
用 StandardCharsets.UTF_8 替代字符串字面量的典型场景
几乎所有需要传入 Charset 或编码名的地方都适用,尤其注意这些高频位置:
-
String.getBytes(StandardCharsets.UTF_8)—— 比getBytes("UTF-8")更安全,避免抛出已检查异常 -
new String(byteArray, StandardCharsets.UTF_8)—— 不再需要 try-catchUnsupportedEncodingException -
Files.readString(path, StandardCharsets.UTF_8)(JDK 11+)和Files.write(path, lines, StandardCharsets.UTF_8) -
InputStreamReader(inputStream, StandardCharsets.UTF_8)和OutputStreamWriter(outputStream, StandardCharsets.UTF_8)
哪些编码名有对应常量?哪些没有?
StandardCharsets 只包含 ISO/IEC 和 IETF 标准认可的最小集合,共 7 个:
-
US_ASCII、ISO_8859_1、UTF_8、UTF_16、UTF_16BE、UTF_16LE - 没有
GBK、GB2312、Big5、Windows-1252等非标准或平台相关编码 —— 这些仍需用字符串,但应封装为静态 final 字符串并加注释说明来源 - JDK 不保证所有系统都支持非
StandardCharsets编码,调用Charset.forName("GBK")仍可能抛UnsupportedCharsetException
兼容性与性能影响几乎为零
使用常量不会带来运行时开销:每个字段是静态 final 的 Charset 实例,JVM 类加载时初始化一次;相比每次调用 Charset.forName("UTF-8"),它省去了字符串查找和缓存同步逻辑。兼容性方面,StandardCharsets 自 JDK 7 起存在,Android API 19+(KitKat)也完整支持。唯一要注意的是:若项目必须兼容 JDK 6 或更早版本,则无法使用,需降级为字符串 + 异常捕获模式。
立即学习“Java免费学习笔记(深入)”;
真正容易被忽略的是跨平台文件读写场景 —— 比如用 StandardCharsets.UTF_8 写出的文件,在 Windows 记事本里可能显示为 ANSI,不是因为编码错,而是记事本默认不识别 UTF-8 BOM;这时候得明确是否要写 BOM,而 StandardCharsets 本身不控制 BOM 行为,需额外处理。


















