以下代码是有效的Java程序。
public class Foo
{
public static void \u006d\u0061\u0069\u006e(String[] args)
{
System.out.println("hello, world");
}
}
使用Unicode转义序列编写main
标识符。它编译并运行良好。
$ 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
以下程序是错误的,因为用于编写m
的{{1}}的转义序列无效。
main
编译器抱怨非法的unicode序列。
public class Foo
{
public static void \u6d\u0061\u0069\u006e(String[] args)
{
System.out.println("hello, world");
}
}
让我感到惊讶的是,即使非法的unicode转义序列似乎出现在评论中,以下程序也无效。
$ javac Foo.java && java Foo
Foo.java:3: error: illegal unicode escape
public static void \u6d\u0061\u0069\u006e(String[] args)
^
Foo.java:3: error: invalid method declaration; return type required
public static void \u6d\u0061\u0069\u006e(String[] args)
^
2 error
这是错误。
public class Foo
{
// This comment contains \u6d.
public static void main(String[] args)
{
System.out.println("hello, world");
}
}
编译器抱怨非法unicode转义序列,尽管它似乎在评论中。
当我们看到JLS §3.7中如何定义行尾注释时,此行为背后的原因就变得清晰了。
$ javac Foo.java && java Foo
Foo.java:3: error: illegal unicode escape
// This comment contains \u6d.
^
1 error
JLS §3.4定义EndOfLineComment:
/ / {InputCharacter}
如下。
InputCharacter
最后,JLS §3.3定义InputCharacter:
UnicodeInputCharacter but not CR or LF
如下。
UnicodeInputCharacter
因此,词法分析器需要首先识别Unicode转义序列以识别注释,如果发现非法的Unicode转义序列,则词法分析将失败并发生错误。因此,编译器永远不会继续识别包含非法Unicode转义序列的注释。
虽然我曾经认为从评论开头(比如说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转义序列可能导致词法分析失败。
在解析注释时还有什么可能导致编译器失败?
答案 0 :(得分:2)
短:
没什么(没有 else )。
长:
逻辑上,{<1}}转义序列在词法处理(扫描/标记化)发生之前处理。根据{{3}}:
使用以下三个词汇翻译步骤将原始Unicode字符流转换为一系列标记,这些步骤依次应用:
将Unicode字符的原始流中的Unicode转义(第3.3节)转换为相应的Unicode字符。形式为\ uxxxx的Unicode转义,其中xxxx是十六进制值,表示编码为xxxx的UTF-16代码单元。此转换步骤允许任何程序仅使用ASCII字符表示。
将步骤1产生的Unicode流转换为输入字符和行终止符流(§3.4)。
- 醇>
将步骤2产生的输入字符和行终止符流转换为输入元素序列(第3.5节),在白色空间(第3.6节)和注释(第3.7节)被丢弃之后,令牌(§3.5),它们是句法语法的终点符号(§2.3)。
从技术上讲,您示例中的\u
NOT 是评论的一部分。是否属于该评论是在之后确定的将其转换回unicode代码点。但遗憾的是它失败了。
作为证明,下面的课应该编译:
\u6d