Java中的Unicode转义语法

23

在Java中,我学到了以下语法可用于提及不在键盘上的Unicode字符(例如非ASCII字符):

(\u)(u)*(HexDigit)(HexDigit)(HexDigit)(HexDigit)

我的问题是:在上述语法中,(u)* 的目的是什么?

我理解的一个使用案例是,在Java中表示日元符号:

char ch = '\u00A5';

哇,我还以为我已经了解了所有关于Java字符串字面量的知识呢XD - Franz D.
3个回答

34
有趣的问题。JLS的第3.3节(请参阅)中提到:
UnicodeEscape:
    \ UnicodeMarker HexDigit HexDigit HexDigit HexDigit

UnicodeMarker:
    u
    UnicodeMarker u

这意味着转义为\\u+\p{XDigit}{4}

如果一个合法的反斜杠后面跟着u或多个u,并且最后一个u后面没有四个十六进制数字,则会在编译时出现错误。

所以你是对的,反斜杠后面可以有一个或多个u。原因在下面给出:

Java编程语言规定了一种标准方法,将Unicode编写的程序转换为ASCII,将程序转换为可以由基于ASCII的工具处理的形式。 转换涉及通过添加额外的u将程序源文本中的任何Unicode转义序列转换为ASCII-例如,\uxxxx变为\uuxxxx-同时将源文本中的非ASCII字符转换为包含单个u的Unicode转义。

此转换版本对Java编译器同样可接受,并表示完全相同的程序。 精确的Unicode源代码可以稍后从此ASCII形式恢复,方法是将每个存在多个u的转义序列转换为少一个u的Unicode字符序列,同时将每个带有单个u的转义序列转换为相应的单个Unicode字符。

所以这个输入

 \u0020ä

变成

 \uu0020\u00e4

第一个 uu 表示“这是一个 Unicode 转义序列”,而第二个 u 表示“自动工具将非 ASCII 字符转换为 Unicode 转义序列”。
当您想将 ASCII 转换回 Unicode 时,此信息非常有用:您可以尽可能地恢复原始代码。

5

这意味着您可以添加任意数量的 u ,例如以下几行代码是等价的:

char ch = '\u00A5';
char ch = '\uuuuu00A5';
char ch = '\uuuuuuuuuuuuuuuuuu00A5';

(并且所有编译)

我删除了我的评论。我错了,而且我也误解了他的问题,很抱歉。 - Xabster
Java允许额外的u是有什么想法吗?因为我们看到'\u00A5'与'\uuuuu00A5'相同。 - user3265048
@user3265048 Aaron解释了为什么允许这样做 - 基本上是作为编译器的Unicode标记。 - assylias
啊!!我上次没有看到Aaron的更新。我已经得到了答案。但是你说的ASCII工具是什么意思?Eclipse能够提供日元符号,所以你的意思是Eclipse不仅仅是ASCII工具? - user3265048
@user3265048,是的,Eclipse在源代码中使用正确的Unicode字符等方面表现良好。但是有一些简单的命令行工具无法处理非ASCII字符。 - Paul Stelian

1

Java仅支持使用\uXXXX(4个十六进制字符)的表示法来表示BMP中的Unicode字符,但不支持使用\u{YYYYY}(5个十六进制字符)的表示法来表示BMP之外的字符(16个其他平面)。因此,无法将它们表示为单个常量字符,您必须将它们写成代理对。

例如,如果要编写MATHEMATICAL BOLD CAPITAL A(U+1D400),则不能编写"u\{1D400}",这是Java中非法的Unicode转义序列。编写"u\1D400"只会输出ᵀ0,因为它实际上是"u\1D40" + "0"。现在您真的必须在Java中使用代理。因此,您必须编写"\uD835\uDC00"

但是直接编写代理并不方便,因此,如果要直接从代码点编写它们,则可以使用以下其中一种技巧:

String test1 = new String(new int[] { 0x1D400 }, 0, 1);
String test2 = String.valueOf(Character.toChars(0x1D400));
String test3 = Character.toString(0x1D400):

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接