- 转义序列:在字符串中,用
\uXXXX的形式表示一个字符,XXXX是该字符的 4 位或 8 位十六进制 Unicode 码点,这是 Java 源代码中直接书写 Unicode 字符的方式。 - 码点表示:直接显示字符的十进制或十六进制码点值,
U+4E2D表示“中”字。
下面我将详细介绍如何在 Java 中实现这两种转换,并提供清晰的代码示例。
转换为 Unicode 转义序列 (\uXXXX)
这是最常见的需求,通常用于在代码中生成包含特殊字符的字符串,或者在日志、配置文件中安全地显示非 ASCII 字符。
核心思路
遍历字符串中的每一个字符,获取其 Unicode 码点,然后将该码点格式化为 \u 后跟 4 位或 8 位十六进制数的形式。
代码实现
这里提供一个健壮的工具方法,它可以正确处理所有 Unicode 字符,包括那些需要 8 位(代理对,Surrogate Pair)表示的字符(如 Emoji)。
import java.util.Locale;
public class UnicodeConverter {
/**
* 将字符串转换为 Unicode 转义序列形式。
* 将 "你好" 转换为 "\u4F60\u597D"。
*
* @param str 要转换的字符串
* @return 转换后的 Unicode 字符串
*/
public static String stringToUnicodeEscapes(String str) {
if (str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
// 对于基本多文种平面 (BMP) 中的字符,码点 <= 0xFFFF
if (ch < 0x10000) {
sb.append(String.format("\\u%04X", (int) ch));
}
// 对于辅助平面 (Supplementary Planes) 中的字符,需要使用代理对
// Emoji 表情符号,码点 > 0xFFFF
else {
// 将码点分解为高位和低位代理
int codePoint = str.codePointAt(i);
sb.append(String.format("\\u%04X\\u%04X",
Character.highSurrogate(codePoint),
Character.lowSurrogate(codePoint)));
// 因为 codePointAt 会消耗两个 char,所以这里 i 需要额外增加
i++;
}
}
return sb.toString();
}
public static void main(String[] args) {
// 示例 1: 常见的中文字符
String chineseStr = "你好,世界!Hello World!";
System.out.println("原始字符串: " + chineseStr);
System.out.println("Unicode 转义: " + stringToUnicodeEscapes(chineseStr));
// 输出: \u4F60\u597D\uFF0C\u4E16\u754C\uFF01Hello World!
System.out.println("--------------------");
// 示例 2: Emoji (位于辅助平面,需要8位表示)
String emojiStr = "😊 Java";
System.out.println("原始字符串: " + emojiStr);
System.out.println("Unicode 转义: " + stringToUnicodeEscapes(emojiStr));
// 输出: \uD83D\uDE00 Java
// 😊 的码点是 U+1F60D,其高位代理是 \uD83D,低位代理是 \uDE00
System.out.println("--------------------");
// 示例 3: 空字符串
String emptyStr = "";
System.out.println("原始字符串: " + emptyStr);
System.out.println("Unicode 转义: " + stringToUnicodeEscapes(emptyStr));
// 输出: (空字符串)
}
}
代码解释:
StringBuilder: 用于高效地构建最终的字符串。str.charAt(i): 获取字符串中指定索引的char。ch < 0x10000: 判断字符是否在基本多文种平面,大部分常用字符(包括中文、拉丁字母等)都在这个平面。String.format("\\u%04X", (int) ch):%04X: 将整数格式化为 4 位、大写的十六进制数,不足4位前面补零。\\u:\\是一个反斜杠的转义,所以最终会输出\u。
str.codePointAt(i): 对于 BMP 之外的字符(如 Emoji),char无法完整表示一个字符,需要int类型的码点,这个方法可以直接获取从位置i开始的完整字符的码点。Character.highSurrogate(codePoint)和Character.lowSurrogate(codePoint): 将一个辅助平面的码点分解成两个char(高位和低位代理)。i++: 由于codePointAt读取了两个char的位置,所以循环变量i需要额外自增一次,以跳过下一个char。
显示字符的 Unicode 码点 (如 U+4E2D)
这种方法不生成 \uXXXX 转义序列,而是直接显示每个字符对应的 Unicode 码点值,常用于调试或分析字符串内容。
核心思路
遍历字符串,对每个字符使用 Character.codePointAt() 获取其码点,然后格式化输出。
代码实现
import java.util.Locale;
public class UnicodeCodePointViewer {
/**
* 将字符串的每个字符及其 Unicode 码点打印出来。
*
* @param str 要分析的字符串
*/
public static void printCodePoints(String str) {
if (str == null) {
System.out.println("字符串为 null");
return;
}
System.out.println("字符串: \"" + str + "\"");
System.out.println("字符码点分析:");
for (int i = 0; i < str.length(); ) {
int codePoint = str.codePointAt(i);
// 获取字符的 Unicode 表示 (如 U+4E2D)
String hexCodePoint = String.format("U+%04X", codePoint).toUpperCase(Locale.ROOT);
// 获取字符本身
char[] chars = Character.toChars(codePoint);
String character = new String(chars);
System.out.printf("字符: '%s' -> 码点: %s (十进制: %d)%n", character, hexCodePoint, codePoint);
// 移动到下一个字符
i += Character.charCount(codePoint);
}
}
public static void main(String[] args) {
String testStr = "A中😊";
printCodePoints(testStr);
}
}
输出结果:
字符串: "A中😊"
字符码点分析:
字符: 'A' -> 码点: U+0041 (十进制: 65)
字符: '中' -> 码点: U+4E2D (十进制: 20013)
字符: '😊' -> 码点: U+1F60D (十进制: 128521)
代码解释:
str.codePointAt(i): 获取从位置i开始的完整字符的码点。Character.charCount(codePoint): 这是一个关键方法,它返回表示给定码点所需的char数量,对于 BMP 字符,返回 1;对于辅助平面字符,返回 2,这确保了我们能正确地遍历整个字符串,尤其是在处理 Emoji 时。i += Character.charCount(codePoint): 根据当前字符占用的char数量来更新索引i,确保循环不会出错。Character.toChars(codePoint): 将一个码点转换为一个或两个char组成的数组,然后可以用来重建原始字符。
| 需求 | 方法 | 关键技术 | 适用场景 |
|---|---|---|---|
转为 \uXXXX 转义序列 |
stringToUnicodeEscapes() |
String.format, Character.highSurrogate/lowSurrogate, codePointAt |
在源代码、JSON、XML 中安全地表示非ASCII字符;生成特定格式的字符串。 |
| 显示字符的码点 | printCodePoints() |
codePointAt, Character.charCount, Character.toChars |
调试、日志分析、理解字符串的内部编码结构。 |
选择哪种方法取决于你的具体目标,如果你想在 Java 程序中生成一个包含特殊字符的字符串字面量,使用方法一,如果你想查看或分析字符串中每个字符的编码信息,使用方法二。
