什么会导致Java编译器在解析注释时失败?
下面的代码是一个有效的Java程序什么会导致Java编译器在解析注释时失败?,java,unicode,comments,grammar,lexical-analysis,Java,Unicode,Comments,Grammar,Lexical Analysis,下面的代码是一个有效的Java程序 public class Foo { public static void \u006d\u0061\u0069\u006e(String[] args) { System.out.println("hello, world"); } } main标识符是使用Unicode转义序列编写的。它编译和运行良好 $ javac Foo.java && java Foo hello, world 虽然下面的细
public class Foo
{
public static void \u006d\u0061\u0069\u006e(String[] args)
{
System.out.println("hello, world");
}
}
main
标识符是使用Unicode转义序列编写的。它编译和运行良好
$ javac Foo.java && java Foo
hello, world
虽然下面的细节对于这个问题可能不是必需的,但我还是分享它,以防有人对此感到好奇。我在Debian8.0上使用OpenJDK的Java编译器,但我在这个问题上提出的问题应该适用于任何Java编译器
$ javac -version
javac 1.7.0_79
$ readlink -f $(which javac)
/usr/lib/jvm/java-7-openjdk-amd64/bin/javac
以下程序出错,因为用于写入main
的m
的转义序列无效
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
令我惊讶的是,下面的程序也是无效的,尽管非法的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转义序列非法,尽管它似乎在注释中
public class Foo
{
// This comment contains \u6d.
public static void main(String[] args)
{
System.out.println("hello, world");
}
}
当我们看到中如何定义行末注释时,这种行为背后的原因就变得很清楚了
定义InputCharacter
,如下所示
InputCharacter:
UnicodeInputCharacter but not CR or LF
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
最后,定义UnicodeInputCharacter
,如下所示
InputCharacter:
UnicodeInputCharacter but not CR or LF
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转义序列的注释
$ 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
虽然我过去认为从注释开始(比如/
)到结束的所有内容都被忽略,但上面的示例表明情况并非如此,因为词法分析器必须识别注释开始和注释结束之间的Unicode转义序列,非法的Unicode转义序列会导致词法分析失败
还有什么会导致编译器在分析注释时失败?Short:
没有(没有其他内容)
长:
从逻辑上讲,\u
转义序列是在词法处理(扫描/标记化)发生之前处理的。根据:
原始Unicode字符流使用以下三个词汇转换步骤转换为一系列标记,这三个步骤依次应用:
\u6d
不是注释的一部分。在将其翻译回unicode代码点后,将确定它是否属于该注释。但不幸的是,它失败了
作为证明,应编译以下类:
public class Test {
// is comment, the rest, not\u000a public static void main( String[] args) {
System.out.println("See!");
}
}
look@Dando18谢谢分享链接。然而,没有一个答案能真正回答这个问题。关于
@deprecated
的答案在OpenJDK中是不可复制的。由于此Unicode字符'*/'*/而提到/*编译器错误的答案是不正确的,因为后面的*/
显然不在注释中。其他两个答案并没有解决所问的具体问题。实际上,@deprecated
答案可以使用javac-Xlint
复制(前提是@deprecated
在javadoc注释中(/**@deprecated*/
)@realpoint你能分享一下你在javadoc评论中使用@deprecated
,然后用javac-Xlint
编译的代码和错误吗?我无法用复制任何错误。我用javac-Xlint
以及javac-Xlint编译了它,但没有发生任何错误。我想你应该是这样的强调为什么JLS的这一部分意味着没有其他东西会导致评论中出现错误,更不用说OP似乎已经理解的错误原因了。