为什么一些ASCII字符不能在Java源代码中以“\ uXXXX”的forms表示?
今天我又偶然发现了这个:
class Test { char ok = '\n'; char okAsWell = '\u000B'; char error = '\u000A'; }
它不会编译:
第4行中的字符常量无效。
编译器似乎坚持我写'\ n'来代替。 我看不出有什么理由,但这很烦人。
是否有一个合乎逻辑的解释,为什么具有特殊符号的字符(如\t
, \n
, \r
) 必须以Java源代码的formsexpression?
Unicode字符被它们的值replace,所以你的行被编译器replace:
char error = ' ';
这不是一个有效的Java语句。
这是语言规范所规定的:
用于Java编程语言(“Java编译器”)的编译器首先识别其input中的Unicode转义,将ASCII字符\ u后跟四个hex数字转换为指定的hex值的UTF-16代码单元(第3.1节)所有其他字符不变。 表示补充字符需要连续两次Unicode转义。 该翻译步骤产生一系列Unicodeinput字符。
这可能会导致令人惊讶的东西,例如,这是一个有效的Java程序(它包含隐藏的Unicode字符) – 彼得·劳瑞礼貌 :
public static void main(String[] args) { for (char ch = 0; ch < Character.MAX_VALUE; ch++) { if (Character.isJavaIdentifierPart(ch) && !Character.isJavaIdentifierStart(ch)) { System.out.printf("%04x <%s>%n", (int) ch, "" + ch); } } }
在Java编译器对源代码执行其他任何操作之前, 像\u000a
这样的Unicode转义序列被它们代表的实际字符replace 。 所以,你的程序最终会以
char ch = ' ';
因此,源代码中的\u000a
在内部被一个换行字符replace。 请注意,这是在编译器实际读取和解释源代码之前发生的。
参考Java语言规范 :
对于行结束符 (§3.4)出现在“结束之前”和“结束之前”是一个编译时错误。
而且所有人都知道, \n
是一个行结束符 ,引用:
LineTerminator: the ASCII LF character, also known as "newline" the ASCII CR character, also known as "return" the ASCII CR character followed by the ASCII LF character
其他可能导致问题的符号是"
, '
和"
例如。
我认为原因是在parsing代码时扩展了\uXXXX
序列,参见JLS§3.2。 词汇翻译 。
在3.3中描述。 Unicode转义http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html 。 Javac首先在.java中find\ uxxxx序列,并用真正的字符replace它们然后编译。 的情况下
char error = '\u000A';
\ u000A将被replace为newline
(10),实际的文本将会被replace
char error = ' ';
因为编译器将它们视为未转义的文本。
这是有效的代码:
class \u00C9 {}