diff --git a/contents/why-is-executing-java-code-in-comments-with-certain-unicode-characters-allowed.md b/contents/why-is-executing-java-code-in-comments-with-certain-unicode-characters-allowed.md new file mode 100644 index 0000000..a4ef565 --- /dev/null +++ b/contents/why-is-executing-java-code-in-comments-with-certain-unicode-characters-allowed.md @@ -0,0 +1,73 @@ + +## 为什么在注释中可以通过使用特定的 Unicode 字符来执行 Java 代码? +### 问题 +下列的代码产生了 "Hello World!" 的输出(真的,试试吧). + +``` + public static void main(String... args) { + // The comment below is not a typo. + // \u000d System.out.println("Hello World!"); + } +``` + +出现这种结果的原因是 Java 编译器把 \u000d 解析成了一个换行符然后代码就变成了这样: + +``` + public static void main(String... args) { + // The comment below is not a typo. + // + System.out.println("Hello World!"); + } + +``` +因此才造成了一行注释被 "执行". + +由于这可以被用于 "隐藏" 恶意代码或者怀有恶意的程序员可能作出的其他欺骗行为, 那 +为什么在注释中这么做会被允许呢? + +又为什么被 Java 语言规范所允许? + +## 回答 + +- "为什么可以" 这种问题对我来说似乎带有主观性. 语言的设计者决定这样做, 还有必要 +知道其他的原因吗? 除非你找到作出这个决定的人对这个决定的解释, 否则我们都只能猜. + +- Unicode 解码发生在任何词法语法翻译之前. 这种做法的重要好处是使得在 ASCII 码和 +其他编码之间的转换变得容易. 你甚至不需要找出注释从哪开始, 到哪结束. + +正如 ((Java 语言规范 (Java Language Specification, JLS)) 3.3 节)[https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.3] +中所陈述: 这样允许任何基于 ASCII 码的工具能够处理源文件: + +> [...] Java 编程语言制定了一个标准的方法来把一个用 Unicode 编码编写的程序转换成 + ASCII 编码的, 以此让这个程序能够被一些基于 ASCII 编码的工具所处理. [...] + +这就给平台无关性 (所支持的字符集的无关性) 一个基本的保障, 而这个平台无关性也一直 +是 Java 的重要目标. + +能够在源文件任何地方使用 Unicode 字符是一种简洁的特性. 特别是当 JavaDoc 文档是非 +拉丁语言的时候, 在注释中能使用 Unicode 字符就更加重要了. + +事实上和这个主题相关的还有很多陷阱, Joshua Bloch 和 Neal Gafter 的 +(Java Puzzlers)[http://www.javapuzzlers.com/] (Java 解惑) 中包含了以下的一个变种: + +> 这是一个合法的 Java 程序吗, 如果是, 它有什么输出? +``` +\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020\u0020 +\u0063\u006c\u0061\u0073\u0073\u0020\u0055\u0067\u006c\u0079 +\u007b\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020 +\u0020\u0020\u0020\u0020\u0073\u0074\u0061\u0074\u0069\u0063 +\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028 +\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0020 +\u0020\u0020\u0020\u0020\u0061\u0072\u0067\u0073\u0029\u007b +\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074 +\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0020 +\u0022\u0048\u0065\u006c\u006c\u006f\u0020\u0077\u0022\u002b +\u0022\u006f\u0072\u006c\u0064\u0022\u0029\u003b\u007d\u007d +``` + +(这个程序最终也就是一个普普通通的 "Hello Wold" 程序而已.) + +在这个谜团的答案中, 他们 (Java Puzzler 的作者) 指出: +> 更严格地来说, 这个谜团是用来加强前三节课程的: 在你需要插入一些字符, +要插入这些字符无法用其他方式达到, 那么 Unicode 转义就是完全必要的. 但是在其他 +任何情况下, 要避免使用他们.

AltStyle によって変換されたページ (->オリジナル) /