Тут є невидимі символи, які змінюють спосіб відображення коду. У 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 .