Java中Unicode处理需区分编译期字面量(如u4E2D)和运行时解码(如"u4E2D"),前者由编译器直接转换,后者需正则匹配并parseInt转义;高码点Emoji须用codePoint而非char操作。

Java 中 Unicode 编码在变量中正确表示与转换,关键在于区分两种常见场景:一是用 uXXXX 字面量直接声明字符或字符串;二是运行时动态解析形如 "\u4E2D" 的转义字符串。前者由编译器处理,后者需手动解码——混淆这两者是乱码和方块字符的主因。
Unicode 字面量:编译期直接生效
Java 源码中以 u 开头的 4 位十六进制序列(如 u4E2D)是编译期字面量,会被直接替换为对应字符。它只支持 BMP 平面内码点(U+0000 至 U+FFFF),且必须写在源文件里,不能拼接或运行时生成。
-
String s = "u4E2Du6587";→ 正确,编译后就是“中文” -
String s = "\u4E2D\u6587";→ 错误,这是 10 个普通字符,不是 Unicode 转义 -
char c = 'u1F601';→ 编译失败,U+1F601 超出 char 表示范围(需代理对)
运行时解码:处理字符串中的 uXXXX
当接口返回或配置文件中含 "u4E2Du6587" 这类带双反斜杠的字符串时,需用正则匹配并逐段转义。核心是提取 4 位十六进制,再用 (char)Integer.parseInt(hex, 16) 转为字符——仅适用于 BMP 内字符。
- 匹配模式:
Pattern.compile("\\u([0-9a-fA-F]{4})")(注意双反斜杠) - 替换逻辑:对每个匹配组
group(1)解析为 int,强转为 char,再转成字符串 - 示例输入
"\u4E2D\u6587"→ 输出"中文"
支持 Emoji 等高码点:用 codePoint 而非 char
U+1F601(?)、U+1F916(?)等超出 BMP 的码点,不能用 char 表示。必须使用 int 类型码点,并通过 Character.toString(int) 或 String.valueOf(Character.toChars(int)) 生成正确字符串。
立即学习“Java免费学习笔记(深入)”;
-
String s = Character.toString(0x1F601);→ 返回长度为 2 的字符串(代理对),显示为 ? -
int cp = "?".codePointAt(0);→ 获取首字符码点(0x1F601),而非charAt(0)返回的代理高位 - 遍历含高码点字符串:用
String.codePoints().forEach(...),避免按 char 切割出错
双向工具方法:统一处理编码与解码
实际项目中建议封装工具类,覆盖常见需求:
-
toUnicodeEscapes(String s):把“中文”转成"\u4E2D\u6587" -
fromUnicodeEscapes(String s):把"\u4E2D\u6587"还原为“中文” -
toCodePoints(String s):返回所有码点列表(自动跳过代理低位,适配 emoji) - 对非法转义(如
"\uGGGG")应抛异常或跳过,不静默失败


















