以下代码生成输出"Hello World!"(不,真的,试试看).

public static void main(String... args) {

   // The comment below is not a typo.
   // \u000d System.out.println("Hello World!");
}

原因是Java编译器将Unicode字符\u000d解析为新行,并转换为:

public static void main(String... args) {

   // The comment below is not a typo.
   //
   System.out.println("Hello World!");
}

从而导致 comments 被"执行".

因为这可以用来"隐藏"恶意代码或任何邪恶的程序员能想到的东西,why is it allowed in comments

为什么Java规范允许这样做?

推荐答案

Unicode解码发生在任何其他词汇翻译之前.这样做的主要好处是,它使得在ASCII和任何其他编码之间来回切换变得非常简单.你甚至不需要弄清楚 comments 的开始和结束!

JLS Section 3.3所述,这允许任何基于ASCII的工具处理源文件:

[...] Java编程语言指定了一种将Unicode编写的程序转换为ASCII的标准方法,该方法可以将程序转换为可由基于ASCII的工具处理的形式.[...]

这为平台独立性(支持的字符集的独立性)提供了基本保证,而平台独立性一直是Java平台的关键目标.

能够在文件中的任意位置写入任何Unicode字符是一项简洁的功能,在用非拉丁语言记录代码时,在注释中尤其重要.它可以以如此微妙的方式干扰语义,这只是一个(不幸的)副作用.

关于这一主题,有很多gotchas,Joshua Bloch和Neal Gafter的Java Puzzlers篇文章包括以下变体:

这是合法的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 World"程序.)

在解决这个难题时,他们指出了以下几点:

更严重的是,这个谜题强化了前三个谜题的教训:Unicode escapes are essential when you need to insert characters that can’t be represented in any other way into your program. Avoid them in all other cases.


资料来源:Java: Executing code in comments?!

Java相关问答推荐

内容处置 destruct 了PSP请求

gitlab ci不会运行我的脚本,因为它需要数据库连接'

给定Java枚举类,通过值查找枚举

对于几乎不涉及逻辑的请求,您是否应该使用命令模式?

使用Testcontainers与OpenLiberty Server进行集成测试会抛出SocketException

FALSE:它应该在什么时候使用?

只需最少的代码更改即可将版本号标记添加到日志(log)

如何对多个字段进行分组和排序?

为什么Spring Boot项目无法为基于MySQL的CRUD应用程序找到从JPARepository接口扩展的ProductRepository?

虚拟线程应该很快消亡吗?

无法使用Freemarker从XML中读取重复的标记值

try 使用类来包含JSON响应

从LineChart<;字符串、字符串和gt;中删除数据时出现特殊的ClassCastException;

无法将GSON导入到我的JavaFX Maven项目

通过/失败的参数化junit测试方法执行数

如何使用Hibernate v6.2构建NamingStrategy,以表名作为所有列的前缀?

如何使用stream.allMatch()为空流返回false?

ReturnedRect在升级后反转

Java泛型方法重载

简化每个元素本身都是 map 列表的列表