这是我在网上找到的一些代码:
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!
打印到屏幕上;你可以看到它运行here .我可以清楚地看到 public static void main
写的,但它是倒退的。这段代码是如何工作的?这甚至如何编译?
编辑:我在 IntellIJ 中尝试了这段代码,它运行良好。但是,由于某种原因,它在 notepad++ 和 cmd 中不起作用。我还没有找到解决方案,所以如果有人找到,请在下方评论。
这里有一些不可见的字符会改变代码的显示方式。在 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
字符,它是一个从右到左的覆盖,开始一个所有字符都强制从右到左显示的 block ,以及 \u202D
,这是一个从左到右的覆盖,开始一个嵌套 block ,其中所有字符被强制为从左到右的顺序,覆盖第一个覆盖。
所以,当它显示原始代码时,class M
正常显示,但是\u202E
将所有内容的显示顺序从那里颠倒到\u202D
,再次反转一切。 (正式地,从 \u202D
到行终止符的所有内容都被反转了两次,一次是由于 \u202D
而其余的文本由于 而反转>\u202E
,这就是为什么这个文本显示在行中间而不是行尾的原因。)由于行终止符,下一行的方向性独立于第一行的方向性处理,所以 {'H ','e','l','l','o','','W','o','r','l','d','!'});}}
正常显示。
关于完整的(极其复杂,几十页长)Unicode 双向算法,见 Unicode Standard Annex #9 .
我是一名优秀的程序员,十分优秀!