- 将 Unicode 转义序列(如
\u4e2d)转换成对应的字符。 - 将包含非 ASCII 字符(如中文)的字节数组或字符串,按照指定的字符集(如 UTF-8)正确解码成字符。
我会分别对这两种情况进行详细说明,并提供代码示例。

解码 Unicode 转义序列
在 Java 源代码、JSON 字符串、网络数据等地方,我们经常能看到形如 \uXXXX 的序列,XXXX 是一个 16 位的十六进制数,代表一个 Unicode 字符的码点,Java 提供了多种方法来将其解码成实际的字符。
方法 1:使用 String 构造函数 (最直接)
这是最简单直接的方法。String 类有一个构造函数 String(char[] value),我们可以先根据 \u 序列构建一个 char 数组,然后用它来创建字符串。
public class UnicodeDecoder {
public static void main(String[] args) {
// 示例:解码 "\u4e2d\u6587" (应该得到 "中文")
String unicodeStr = "\\u4e2d\\u6587"; // 注意:在 Java 字符串中,反斜杠是转义字符,所以需要写成 "\\u"
// 方法1:手动解析并构建 char 数组
StringBuilder sb = new StringBuilder();
// 使用正则表达式查找所有 \uXXXX 模式
Pattern pattern = Pattern.compile("\\\\u([0-9a-fA-F]{4})");
Matcher matcher = pattern.matcher(unicodeStr);
while (matcher.find()) {
// 将十六进制字符串转换为 char
char c = (char) Integer.parseInt(matcher.group(1), 16);
sb.append(c);
}
String decodedStr1 = sb.toString();
System.out.println("方法1解码结果: " + decodedStr1); // 输出: 方法1解码结果: 中文
// 方法2:使用 String.replace() 和 (char) 转换 (更简洁)
// 这种方法适用于所有 \uXXXX 都是4位且连续的情况
String decodedStr2 = unicodeStr
.replace("\\u4e2d", "\u4e2d") // 替换 \u4e2d
.replace("\\u6587", "\u6587"); // 替换 \u6587
System.out.println("方法2解码结果: " + decodedStr2); // 输出: 方法2解码结果: 中文
// 方法3:使用 Apache Commons Lang (推荐,最健壮)
// 如果你正在使用 Apache Commons Lang 库,有一个非常方便的工具类
// String decodedStr3 = StringEscapeUtils.unescapeJava(unicodeStr);
// System.out.println("方法3解码结果: " + decodedStr3); // 输出: 方法3解码结果: 中文
// 需要添加依赖: org.apache.commons:commons-lang3
}
}
代码解释:
Pattern和Matcher: 我们使用正则表达式\\\\u([0-9a-fA-F]{4})来查找所有符合\u后跟4个十六进制数字的模式。\\u: 在正则表达式中,\是转义字符,所以匹配一个字面上的\需要写成\\。([0-9a-fA-F]{4}): 这是一个捕获组,匹配4个0-9, a-f, A-F的字符。
matcher.find(): 查找下一个匹配项。matcher.group(1): 获取第一个捕获组的内容,也就是十六进制字符串,"4e2d"。Integer.parseInt(..., 16): 将十六进制字符串转换为十进制整数。(char): 将整数强制转换为char类型。StringEscapeUtils.unescapeJava(): 这是 Apache Commons Lang 库提供的强大工具,可以处理\n,\t,\",\'等各种 Java 转义字符,也包括\u序列,是生产环境中的首选。
解码字节为字符串 (处理字符编码)
这是另一个常见的场景:我们有一串字节数据(例如从文件、网络请求中读取),需要将其解码成人类可读的字符串,这里的“解码”指的是将字节序列按照特定的字符集(如 UTF-8, GBK, ISO-8859-1)转换成字符。

核心概念:
- 编码: 将字符转换成字节序列的过程。
- 解码: 将字节序列转换成字符的过程。
- 字符集: 定义了字符与字节序列之间的映射规则。编码和解码必须使用相同的字符集,否则会出现乱码。
在 Java 中,String 类的构造函数和 getBytes() 方法是处理这个问题的关键。
方法 1:使用 String 构造函数 (字节 -> 字符)
import java.nio.charset.StandardCharsets;
public class CharsetDecoder {
public static void main(String[] args) {
// 准备一个包含中文字符的字节数组,我们假设它是用 UTF-8 编码的
String originalStr = "你好,世界!Hello, World!";
// 1. 将字符串编码为 UTF-8 字节数组
byte[] utf8Bytes = originalStr.getBytes(StandardCharsets.UTF_8);
System.out.println("UTF-8 字节数组: " + java.util.Arrays.toString(utf8Bytes));
// 2. 将字节数组解码回字符串 (使用正确的字符集)
String decodedFromUtf8 = new String(utf8Bytes, StandardCharsets.UTF_8);
System.out.println("从 UTF-8 解码后的字符串: " + decodedFromUtf8);
System.out.println("解码是否成功? " + originalStr.equals(decodedFromUtf8)); // 输出: true
// 3. 错误示例:使用错误的字符集解码 (会乱码)
// 假设我们错误地用 ISO-8859-1 (Latin-1) 来解码 UTF-8 字节
String wrongDecoded = new String(utf8Bytes, "ISO-8859-1");
System.out.println("使用 ISO-8859-1 错误解码的结果: " + wrongDecoded); // 输出乱码,如 ä½ å¥½ï¼Œä¸–ç•Œï¼Hello, World!
}
}
方法 2:使用 Charset 类 (更灵活)
java.nio.charset.Charset 类提供了更底层的控制,可以处理字符编码和解码错误。
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
public class AdvancedCharsetDecoder {
public static void main(String[] args) throws Exception {
String originalStr = "你好,世界!Hello, World!";
byte[] utf8Bytes = originalStr.getBytes(StandardCharsets.UTF_8);
// 获取 Charset 对象
Charset charset = StandardCharsets.UTF_8;
// 创建 CharsetDecoder
CharsetDecoder decoder = charset.newDecoder();
// 可以配置解码错误处理策略
// REPORT: 遇到无法解码的字节时抛出 CharacterCodingException (默认)
// REPLACE: 用替换字符 (如 �) 替换无法解码的字节
// IGNORE: 忽略无法解码的字节
decoder.onMalformedInput(CodingErrorAction.REPLACE);
decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
// 使用 ByteBuffer 和 CharBuffer 进行解码
ByteBuffer byteBuffer = ByteBuffer.wrap(utf8Bytes);
CharBuffer charBuffer = decoder.decode(byteBuffer);
String decodedStr = charBuffer.toString();
System.out.println("使用 CharsetDecoder 解码结果: " + decodedStr);
}
}
总结与最佳实践
| 场景 | 目标 | 关键方法/类 | 示例 |
|---|---|---|---|
解码 Unicode 转义序列 (\uXXXX) |
将 \u4e2d 变成 中 |
- 手动解析 (正则) - String.replace() - StringEscapeUtils.unescapeJava() (推荐) |
StringEscapeUtils.unescapeJava("\\u4e2d") |
| 解码字节为字符串 | 将 [byte] 变成 "你好" |
- new String(byte[], charset) - Charset 和 CharsetDecoder |
new String(byteArr, StandardCharsets.UTF_8) |
核心要点:
- 明确你的需求:你是要处理
\u这样的文本转义符,还是要处理二进制字节流? - 处理
\u序列:- 简单场景用
String.replace()。 - 复杂或生产环境,强烈推荐使用 Apache Commons Lang 的
StringEscapeUtils.unescapeJava(),因为它健壮且功能全面。
- 简单场景用
- 处理字节流:
- 始终明确指定字符集! 永远不要使用
new String(byte[])这种不指定字符集的构造方法,因为它依赖平台默认编码,极易导致乱码。 - 在现代 Java 开发中,优先使用
StandardCharsets中预定义的常量,如StandardCharsets.UTF_8,StandardCharsets.ISO_8859_1,这比直接写字符串名字(如 "UTF-8")更安全、更高效。 - 如果数据来源不可控,可能需要使用
CharsetDecoder并配置错误处理策略(如REPLACE),以避免程序因解码错误而崩溃。
- 始终明确指定字符集! 永远不要使用
