Java 的字符串字面量可以直接支持 Unicode 转义序列,我们也可以通过编程方式,使用 Character 类来将一个整数(码点)转换为字符。

在字符串字面量中直接使用 Unicode 转义
这是最简单直接的方法,你可以在 Java 源代码的字符串中直接写入 \u 后跟四个十六进制数。
语法
\uXXXX
XXXX 是一个 4 位的十六进制数,代表一个 Unicode 字符的码点。
示例代码
public class UnicodeLiteralExample {
public static void main(String[] args) {
// \u4e2d 是 "中" 的 Unicode 码点
// \u6587 是 "文" 的 Unicode 码点
String chinese = "\u4e2d\u6587";
// \u5b66 是 "学" 的 Unicode 码点
// \u4e60 是 "习" 的 Unicode 码点
String study = "\u5b66\u4e60";
System.out.println(chinese); // 输出: 中文
System.out.println(study); // 输出: 学习
// 也可以混合使用普通字符和 Unicode 转义
String mixed = "Hello, \u4e16\u754c!"; // \u4e16是"世", \u754c是"界"
System.out.println(mixed); // 输出: Hello, 世界!
}
}
注意:这种方法在编译时就已经完成了转换,当 .java 文件被编译成 .class 文件时,\uXXXX 会被替换成它所代表的字符,在反编译 .class 文件时,你看到的将是实际的字符而不是 \uXXXX 序列。
通过 Character.toString() 进行编程解码
如果你有一个 Unicode 码点的整数值,并想在运行时将其转换为字符串,可以使用 Character 类。

示例代码
假设我们有一个整数值,代表 Unicode 码点。
public class UnicodeDecodeProgrammatically {
public static void main(String[] args) {
// "中" 的 Unicode 码点是 0x4E2D,即十进制的 20013
int codePoint = 0x4E2D;
// Character.toString() 方法可以将一个码点转换为字符串
String character = Character.toString(codePoint);
System.out.println("码点: " + codePoint);
System.out.println("对应的字符: " + character); // 输出: 中
// 也可以使用 char 类型 (对于基本多文种平面 BMP 内的字符)
char charValue = (char) codePoint;
String fromChar = Character.toString(charValue);
System.out.println("从 char 转换的字符: " + fromChar); // 输出: 中
}
}
处理超出 BMP 的字符(代理对)
Unicode 字符非常多,很多字符的码点超过了 0xFFFF(即基本多文种平面,BMP),这些字符需要用两个 char 值来表示,这被称为“代理对”(Surrogate Pair)。
- 第一个
char是“高位代理”(High Surrogate),范围是\uD800到\uDBFF。 - 第二个
char是“低位代理”(Low Surrogate),范围是\uDC00到\uDFFF。
对于这些字符,直接使用 char 会丢失信息,必须使用 int 类型的码点。
示例代码
Emoji 表情符号是典型的超出 BMP 的字符。“😂”的码点是 0x1F602。
public class SupplementaryCharacterExample {
public static void main(String[] args) {
// Emoji "笑哭" 的码点是 0x1F602
int codePoint = 0x1F602;
// 正确的方式:使用 int 码点和 Character.toString()
String emoji = Character.toString(codePoint);
System.out.println("使用码点解码: " + emoji); // 输出: 😂
// 错误的方式:尝试用 char
// char c = (char) codePoint; // 这样会得到一个错误的值
// System.out.println(c); // 输出可能是一个无法识别的符号或 '?'
// 如果你有一个代理对(两个 char),如何转换?
char[] surrogatePair = Character.toChars(codePoint);
System.out.println("代理对的长度: " + surrogatePair.length); // 输出: 2
System.out.println("高位代理: " + surrogatePair[0]); // 输出一个高位代理字符,如 \uD83D
System.out.println("低位代理: " + surrogatePair[1]); // 输出一个低位代理字符,如 \uDE02
// 同样,可以用 String 的构造函数从 char 数组创建字符串
String fromSurrogate = new String(surrogatePair);
System.out.println("从代理对创建的字符串: " + fromSurrogate); // 输出: 😂
}
}
从包含 \uXXXX 格式字符串的文本中解码
你可能会从文件、网络或用户输入中获取一个像 "\\u4e2d\\u6587" 这样的字符串,并希望将其解码成“中文”,这种情况下,你需要自己解析这个字符串。
示例代码
下面的方法会扫描字符串,查找 \u 开头的模式,并将其替换为对应的字符。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DecodeUnicodeFromString {
public static void main(String[] args) {
String encodedString = "Hello, \\u4e2d\\u56fd\\uff01"; // 注意:在字符串字面量中,反斜杠需要双写
String decodedString = decodeUnicodeEscapes(encodedString);
System.out.println("解码前: " + encodedString);
System.out.println("解码后: " + decodedString); // 输出: Hello, 中国!
}
public static String decodeUnicodeEscapes(String str) {
// 使用正则表达式匹配 \uXXXX 模式
Pattern pattern = Pattern.compile("\\\\u([0-9a-fA-F]{4})");
Matcher matcher = pattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// 找到匹配的十六进制字符串
String hexStr = matcher.group(1);
// 将十六进制字符串转换为整数(码点)
int codePoint = Integer.parseInt(hexStr, 16);
// 将码点转换为字符
char ch = (char) codePoint;
// 将匹配到的 \uXXXX 替换为字符
matcher.appendReplacement(sb, String.valueOf(ch));
}
// 将剩余部分添加到结果中
matcher.appendTail(sb);
return sb.toString();
}
}
重要提示:当这个包含 \uXXXX 的字符串本身是 Java 字符串字面量时,你需要对反斜杠进行转义,所以写成 "\\u4e2d",如果你是从文件中直接读取的文本,它可能就是 \u4e2d 的形式,不需要双反斜杠。
| 场景 | 推荐方法 | 示例 |
|---|---|---|
| 在源代码中直接写字符 | Unicode 转义序列 | String s = "\u4e2d"; |
| 运行时从整数(码点)转 | Character.toString(int codePoint) |
Character.toString(0x4e2d); |
| 处理 Emoji 等特殊字符 | Character.toChars(int codePoint) |
char[] chars = Character.toChars(0x1F602); |
从文本(如文件)中解码 \uXXXX |
正则表达式替换 | 使用 Pattern 和 Matcher 解析并替换。 |
选择哪种方法取决于你的具体需求,对于在代码中硬编码的字符,方法一最方便,对于动态处理,方法二和方法三更合适,对于处理来自外部数据的字符串,方法四是必要的。
