Why does this code, written backwards, print "Hello World!"
Here is some code that I found on the Internet:
class M{public static void main(String[]a){System.out.print(new char[]
{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
This code prints Hello World!
onto the screen; you can see it run here. I can clearly see public static void main
written, but it is backwards. How does this code work? How does this even compile?
Edit: I tried this code in IntellIJ, and it works fine. However, for some reason it doesn't work in notepad++, along with cmd. I still haven't found a solution to that, so if anyone does, comment down below.
There are invisible characters here that alter how the code is displayed. In Intellij these can be found by copy-pasting the code into an empty string (""
), which replaces them with Unicode escapes, removing their effects and revealing the order the compiler sees.
Here is the output of that copy-paste:
"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','!'});}} "
The source code characters are stored in this order, and the compiler treats them as being in this order, but they're displayed differently.
Note the \u202E
character, which is a right-to-left override, starting a block where all characters are forced to be displayed right-to-left, and the \u202D
, which is a left-to-right override, starting a nested block where all characters are forced into left-to-right order, overriding the first override.
Ergo, when it displays the original code, class M
is displayed normally, but the \u202E
reverses the display order of everything from there to the \u202D
, which reverses everything again. (Formally, everything from the \u202D
to the line terminator gets reversed twice, once due to the \u202D
and once with the rest of the text reversed due to the \u202E
, which is why this text shows up in the middle of the line instead of the end.) The next line's directionality is handled independently of the first's due to the line terminator, so {'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
is displayed normally.
For the full (extremely complex, dozens of pages long) Unicode bidirectional algorithm, see Unicode Standard Annex #9.
It looks different because of the Unicode Bidirectional Algorithm. There are two invisible characters of RLO and LRO that the Unicode Bidirectional Algorithm uses to change the visual appearance of the characters nested between these two metacharacters.
The result is that visually they look in reverse order, but the actual characters in memory are not reversed. You can analyse the results here. The Java compiler will ignore RLO and LRO, and treat them as whitespace which is why the code compiles.
Note 1: This algorithm is used by text editors and browsers to visually display characters both LTR characters (English) and RTL characters (e.g.
Arabic, Hebrew) together at the same time - hence "bi"-directional. You can read more about the Bidirectional Algorithm
at Unicode's website.
Note 2: The exact behaviour of LRO and RLO is defined in Section 2.2 of
the Algorithm.