Тут є невидимі символи, які змінюють спосіб відображення коду. У 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, що є переоправленням зліва направо, починаючи вкладений блок, де всі символи змушені переходити вліво-вправо, переосмислюючи перше заміщення.
Ergo, коли він відображає оригінальний код, class Mвідображається нормально, але \u202Eповертає порядок відображення всього звідти до пункту \u202D, який повертає все знову. (Формально все від \u202Dтермінатора до рядка повертається двічі, один раз за рахунок \u202Dі один раз, коли решта тексту перевернута через \u202E, тому цей текст відображається посередині рядка замість кінця.) Спрямованість наступного рядка керується незалежно від першого через термінатор лінії, тому {'H','e','l','l','o',' ','W','o','r','l','d','!'});}}відображається нормально.
Про повний (надзвичайно складний, десятки сторінок) двонаправлений алгоритм Unicode див. У стандартному додатку Unicode №9 .