为什么某些ASCII字符不能以Java源代码中的'\ uXXXX'形式表示?

Dur*_*dal 57 java

我今天偶然发现了这个问题:

class Test {
    char ok = '\n';
    char okAsWell = '\u000B';
    char error = '\u000A';
}
Run Code Online (Sandbox Code Playgroud)

它不编译:

第4行中的字符常量无效.

编译器似乎坚持要我写'\n'而不是.我没有理由这样做,但它烦人.

有没有为什么有一个特殊的符号字符(比如一个合乎逻辑的解释\t,\n,\r)必须要在Java源代码这种形式表达?

ass*_*ias 85

Unicode字符由其值替换,因此您的行将被编译器替换为:

char error = '
';
Run Code Online (Sandbox Code Playgroud)

这不是有效的Java语句.

这取决于语言规范:

用于Java编程语言的编译器("Java编译器")首先在其输入中识别Unicode转义,将ASCII字符\ u后跟四个十六进制数字转换为指示的十六进制值的UTF-16代码单元(第3.1节),并且传递所有其他字符不变.表示补充字符需要两个连续的Unicode转义.此转换步骤将生成一系列Unicode输入字符.

这可能导致令人惊讶的东西,例如,这是一个有效的Java程序(它包含隐藏的unicode字符) - 由Peter Lawrey提供:

public static void main(String[] args) {
    for (char c??h = 0; c??h < Character.MAX_VALUE; c??h++) {
        if (Character.isJavaIdentifierPart(c??h) && !Character.isJavaIdentifierStart(c??h)) {
            System.out.printf("%04x <%s>%n", (int) c??h, "" + c??h);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • +1很高兴知道.因此,如果我使用`System.out.print("Hello"); //\u000ASystem.out.println("World");`即使第二次打印在评论中是teoreticly,它也会打印"Hello World":D (16认同)
  • 你是第一个,我相信,所以我接受了这一个:)虽然这完美地解释了它背后的原因,但我仍然很好奇为什么语言创造者认为早期扩展是一个好主意.作为一个伟大的WTF,它仍然让我感到震惊. (7认同)
  • +1令人印象深刻的知识,你今天教我一些新东西! (5认同)

poi*_*oae 23

\u000a在Java编译器对源代码执行任何其他操作之前,Unicode转义序列将替换为它们所代表的实际字符.所以,你的程序最终会结束

char ch = '
';
Run Code Online (Sandbox Code Playgroud)

因此\u000a,源代码中的换行符由内部替换.请注意,这在编译器实际读取和解释源代码之前发生.

参考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
Run Code Online (Sandbox Code Playgroud)

可能导致问题的其它符号\,'"例如.