为什么Java编译器在实际编译之前会剥离所有Unicode字符?

4

我对Java非常新手,我有下面这段代码:

    public class Puzzle {
        public static void main(String... args) {
            System.out.println("Hi Guys!");
  //        Character myChar = new Character('\u000d');
       }
    }

您可以看到这条线:

Character myChar = new Character('\u000d');

这个被注释掉了。但是,当我运行javac时,仍然会出现以下错误:

Puzzle.java:9: error: unclosed character literal
//        Character myChar = new Character('\u000d');
                                                  ^
1 error

在这篇博客中,我找到了异常的原因。该博客表示:
Java编译器在实际编译之前会剥离掉所有Unicode字符并将其转换为字符形式。这个解析过程针对的是包括注释在内的整个源代码。在此转换完成后,Java编译过程才会继续执行。
在我们的代码中,当Java编译器遇到\u000d时,它会将其视为换行符并更改代码如下:
public class Puzzle {
    public static void main(String... args) {
        System.out.println("Hi Guys!");
//      Character myChar = new Character('
        ');
   }
}

我有两个问题:

  1. 为什么Java首先解析Unicode?这样做有什么优势吗?
  2. 因为该行仍然被注释,Java正在尝试解析它!这是唯一的情况吗?还是通常也会解析注释行?我很困惑。

提前感谢。


1
问题2的要求不太清楚。最后的代码片段无法编译是明显的。 - Oliver Charlesworth
1
你已经回答了第二个问题 :) Java不解析注释,但在预处理之后,javac看到两行代码,第一行是注释,第二行是')',这是一个语法错误。 - Alex Shesterov
问题1的答案是:否则它何时进行Unicode翻译? - Oliver Charlesworth
个人而言,我希望词法分析器跳过注释中的所有标记。在实际编译之前进行这种处理对我来说似乎不太合逻辑。这样做的好处是什么? - Alexis C.
@ZouZou:为了保持一致性。Unicode翻译只是编译器执行的第一件事情(请参见http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.2)。 - Oliver Charlesworth
1个回答

3
  1. 为什么Java首先解析unicode?它有什么优势吗?

是的,在编译器进行词法分析之前,Unicode序列首先被替换。

引用自 The Java™ Language Specification §3.3 Unicode Escapes

Java编程语言的编译器("Java编译器")首先识别其输入中的Unicode转义符,将ASCII字符\u后跟四个十六进制数字翻译为所指示的十六进制值的UTF-16代码单元(§3.1),并传递所有其他字符不变。

因此,例如以下源代码会导致错误:

// String s = "\u000d";

但这个是有效的:
/*String s = "\u000d";*/

因为当 \u000d 被替换为换行符时,它会变成这样:

/*String s="
";*/

这与多行注释/* */完全相容。

还有以下代码:

public static void main(String[] args) {
    // Comment.\u000d System.out.println("I will be printed out");
    // Comment.\u000a System.out.println("Me too.");
}

将打印出:

I will be printed out
Me too.

因为在替换Unicode后,两个System.out.println()语句将位于注释部分之外。 回答你的问题:Unicode替换必须在某个时刻发生。可以争论是在删除注释之前还是之后进行此操作。选择在删除注释之前进行这一步骤。
推理可能是因为注释只是另一个词法元素,在识别和分析词法元素之前,通常要替换Unicode序列。
看这个例子:
/\u002f This is a comment line

如果放在Java源代码中,它不会引起编译错误,因为\u002f将被转换为字符'/',并且与前面的'/'一起形成一个行注释的开始//
因为这一行仍然被注释了,Java 正在尝试解析它!这是唯一的情况吗?还是通常也会解析注释行?我感到困惑。

Java 编译器不会 分析 注释,但仍需解析以知道其结束位置。


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