下面是我在网上找到的一些代码:
class M{public static void main(String[]a){System.out.print(new char[]
{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
此代码将Hello World!
打印到屏幕上;你可以看到它在这里运行。我可以清楚地看到public static void main
写的,但它是反向的。这段代码是如何工作的?这是如何编译的呢?
编辑:我在IntellIJ中尝试了这段代码,它工作得很好。但是,由于某些原因,它在notepad++和cmd中不起作用。我还没有找到解决方法,所以如果有人找到了,请在下面评论。
字符u+202e
从右到左镜像代码,虽然很巧妙。从M开始隐藏,
"class M\u202E{..."
我是怎么发现这背后的魔力的?
嗯,一开始当我看到这个问题时,我很难回答,“这是一种玩笑,失去别人的时间”,但随后,我打开了我的IDE(“IntelliJ”),创建了一个类,并通过了代码...而且它编译了!!!于是,我仔细看了一下,看到“公共静态空”是向后的,于是我就用光标去了那里,擦除了几个字符……会发生什么呢?字符开始向后抹去,所以,我想....罕见的...我必须执行它...所以我继续执行程序,但首先我需要保存它...就在那时我找到了它!我无法保存文件,因为我的IDE说某些字符有不同的编码,并告诉我它在哪里,所以我开始在Google上研究可以完成这项工作的特殊字符,就这样:)
有点左右
对Unicode双向算法,以及u+202e
所涉及的问题,一个简单说明:
Unicode标准规定了一种称为逻辑顺序的内存表示顺序。当文本以水平线形式呈现时,大多数脚本从左到右显示字符。但是,有几种脚本(如阿拉伯语或希伯来语)显示中水平文本的自然顺序是从右到左。如果所有文本具有统一的水平方向,则显示文本的顺序是明确的。
但是,因为这些从右到左的脚本使用的是从左到右书写的数字,所以文本实际上是双向的:从右到左和从左到右文本的混合。除了数字,来自英语和其他脚本的嵌入式单词也是从左到右书写的,同样产生双向文本。如果没有明确的规范,当文本的水平方向不一致时,在确定显示字符的顺序时会产生歧义。
本附件描述了用于确定双向Unicode文本的方向性的算法。该算法扩展了目前许多现有实现所采用的隐式模型,并针对特殊情况添加了显式格式字符。在大多数情况下,不需要在文本中包含额外的信息来获得正确的显示顺序。
然而,在双向文本的情况下,存在隐含的双向排序不足以产生可理解的文本的情况。为了处理这些情况,定义了一组最小的定向格式化字符,以控制呈现时字符的顺序。这允许精确地控制显示顺序以进行清晰的交换,并确保用于文件名或标签等简单项目的纯文本始终可以正确地排序以供显示。
为什么要创建这样的算法?
bidi算法可以从右到左依次呈现阿拉伯或希伯来字符序列。
由于使用了Unicode双向算法,它看起来有所不同。Unicode双向算法使用RLO和LRO两个不可见字符来更改嵌套在这两个元字符之间的字符的视觉外观。
结果是,从视觉上看,它们的顺序是相反的,但内存中的实际字符并没有颠倒过来。你可以在这里分析结果。Java编译器将忽略RLO和LRO,并将它们视为空白,这就是代码编译的原因。
注1:文本编辑器和浏览器使用该算法同时可视地显示字符LTR字符(英语)和RTL字符(例如阿拉伯语、希伯来语)--因此“双向”--。您可以在Unicode的网站上阅读关于双向算法的更多信息。
注意2:LRO和RLO的确切行为在算法的2.2节中定义。
这里有一些不可见的字符可以改变代码的显示方式。在Intellij中,可以通过将代码复制粘贴到空字符串(“”
)中找到这些代码,这将用Unicode转义替换它们,删除它们的影响并显示编译器看到的顺序。
下面是复制-粘贴的输出:
"class M\u202E{public static void main(String[]a\u202D){System.out.print(new char[]\n"+
"{'H','e','l','l','o',' ','W','o','r','l','d','!'});}} "
源代码字符按此顺序存储,编译器将它们视为按此顺序存储,但它们的显示方式不同。
请注意\u202e
字符,它是从右到左的重写,从一个块开始,所有字符都被迫从右到左显示;\u202d
字符是从左到右的重写,它从一个嵌套块开始,所有字符都被迫按从左到右的顺序显示,重写第一个重写。
因此,当它显示原始代码时,类M
正常显示,但\u202e
将所有内容的显示顺序颠倒到\u202d
中,这又将所有内容颠倒。(形式上,从\u202d
到行终止符的所有内容都会被颠倒两次,一次是由于\u202d
而颠倒的,一次是由于\u202e
而颠倒的,这就是为什么这个文本会出现在行的中间而不是结尾。)由于行终止符,下一行的方向性与第一行的方向性独立处理,因此{'h','e','l','l','o','','w','o','r','l','d',‘!’});}}
正常显示。
关于完整的(极其复杂,长达几十页)Unicode双向算法,请参见Unicode标准附件#9。
我发现了这个怪事: 输出: 这是怎么工作的?
我发现了以下代码。我知道,它看起来没有使用看似随机的数字那么奇怪/令人兴奋,但它似乎比使用大数字上的位移位更复杂: 创意上的代码 输出: 你好,世界 它是如何工作的?它是某种形式的加密还是有人对它的构建感到愤怒?
最近我一直在使用带有大量数字的循环来打印: 我知道这是一种非常愚蠢的方法,但我还从未在Java中使用过任何计时器库。如何修改上述内容,使其每3秒打印一次?
最近,一位同事展示了这段JavaScript代码: 这是怎么工作的?为什么这种行为在浏览器中是可能的,为什么Node.js会自动格式化它?
最近一位同事展示了这个JavaScript代码片段: 这是怎么工作的?为什么这种行为在浏览器中是可能的,为什么Node.js会自动格式化它?
下面的print语句将打印“helloworld”。有人能解释一下吗? 而如下所示: