什么会导致Java编译器在解析注释时失败?

以下代码是一个有效的Java程序。

public class Foo
{
    public static void u006du0061u0069u006e(String[] args)
    {
        System.out.println("hello, world");
    }
}

main标识符是使用Unicode转义序列编写的。 它编译和运行良好。

$ javac Foo.java && java Foo
hello, world

虽然下面的细节可能不需要这个问题,我分享它,以防有人对此感到好奇。 我在Debian 8.0上使用OpenJDK的Java编译器,但是我在这个问题中问的问题应该适用于任何Java编译器。

$ javac -version
javac 1.7.0_79
$ readlink -f $(which javac)
/usr/lib/jvm/java-7-openjdk-amd64/bin/javac

以下程序是错误的,因为用于写入mmain的转义序列无效。

public class Foo
{
    public static void u6du0061u0069u006e(String[] args)
    {
        System.out.println("hello, world");
    }
}

编译器抱怨非法unicode序列。

$ javac Foo.java && java Foo
Foo.java:3: error: illegal unicode escape
    public static void u6du0061u0069u006e(String[] args)
                           ^
Foo.java:3: error: invalid method declaration; return type required
    public static void u6du0061u0069u006e(String[] args)
                            ^
2 error

令我感到惊讶的是,即使非法的Unicode转义序列似乎在注释中,以下程序也是无效的。

public class Foo
{
    // This comment contains u6d.
    public static void main(String[] args)
    {
        System.out.println("hello, world");
    }
}

这是错误。

$ javac Foo.java && java Foo
Foo.java:3: error: illegal unicode escape
    // This comment contains u6d.
                                 ^
1 error

编译器会抱怨非法的Unicode转义序列,尽管它看起来在注释中。

当我们看到如何在JLS§3.7中定义行尾注释时,这种行为背后的原因就变得清晰了。

EndOfLineComment:
/ / {InputCharacter} 

JLS§3.4定义了InputCharacter ,如下所示。

InputCharacter:
  UnicodeInputCharacter but not CR or LF 

最后, UnicodeInputCharacter定义了UnicodeInputCharacter ,如下所示。

UnicodeInputCharacter:
  UnicodeEscape
  RawInputCharacter

UnicodeEscape:
   UnicodeMarker HexDigit HexDigit HexDigit HexDigit

UnicodeMarker:
  u {u}

HexDigit:
  (one of)
  0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

RawInputCharacter:
  any Unicode character

因此,词法分析器需要首先识别Unicode转义序列以识别注释,并且如果找到非法的Unicode转义序列,则词法分析将失败并发生错误。 因此,编译器永远不会继续识别包含非法Unicode转义序列的注释。

尽管我曾经认为从注释开始(比如// )到结束的所有内容都被忽略,但上面的例子表明,情况并非如此,因为词法分析器必须识别注释开始之前的Unicode转义序列和注释的结尾以及非法的Unicode转义序列可能会导致词法分析失败。

还有什么会导致编译器在解析注释时失败?


短:

没有(没有别的 )。

长:

逻辑上, u转义序列词法处理(扫描/标记)发生之前处理。 根据https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.2:

一个原始的Unicode字符流被翻译成一个令牌序列,使用以下三个词法转换步骤,依次应用:

  • Unicode转换(§3.3)在Unicode字符的原始流中转换为相应的Unicode字符。 形式为 uxxxx的Unicode转义符(其中xxxx是十六进制值)表示编码为xxxx的UTF-16编码单元。 该翻译步骤允许任何程序仅使用ASCII字符表示。

  • 将步骤1产生的Unicode流转换为输入字符和行结束符(§3.4)。

  • 将由步骤2产生的输入字符和行终止符的流转换为输入元素序列(第3.5节),在空白区(§3.6)和注释(§3.7)被丢弃之后,该输入元素序列包含标记(§3.5)这是句法语法的终端符号(§2.3)。

  • 因此从技术上讲, u6d在你的例子是评论的一部分。 它是否属于该评论是它被翻译回unicode代码点之后确定的。 但不幸的是,它失败了。

    作为一个证明,下面的类应该编译:

    public class Test {
        // is comment, the rest, notu000a public static void main( String[] args) {
            System.out.println("See!");
        }
    }
    
    链接地址: http://www.djcxy.com/p/20579.html

    上一篇: What can cause Java compiler to fail while parsing a comment?

    下一篇: Java Unicode translation