Hier ist ein Code, den ich im Internet gefunden habe:
class M{public static void main(String[]a){System.out.print(new char[]
{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
Dieser Code wird Hello World!
auf dem Bildschirm gedruckt . Sie können es hier laufen sehen . Ich kann deutlich public static void main
geschrieben sehen, aber es ist rückwärts. Wie funktioniert dieser Code? Wie kompiliert das überhaupt?
Bearbeiten: Ich habe diesen Code in IntellIJ ausprobiert und er funktioniert einwandfrei. Aus irgendeinem Grund funktioniert es jedoch nicht in Notepad ++ zusammen mit cmd. Ich habe immer noch keine Lösung dafür gefunden. Wenn dies jemand tut, kommentieren Sie unten.
java
unicode
right-to-left
Imaginärer Kürbis
quelle
quelle
M
und auch nach[]a
: fileformat.info/info/unicode/char/202d/index.htm Es heißt LEFT-TO-RIGHT OVERRIDEniam diov citats cilbup
klingt wie ein lateinisches Sprichwort ..Antworten:
Hier gibt es unsichtbare Zeichen, die die Anzeige des Codes ändern. In Intellij können Sie diese finden, indem Sie den Code in eine leere Zeichenfolge (
""
) kopieren , die sie durch Unicode-Escapezeichen ersetzt, ihre Effekte entfernt und die Reihenfolge anzeigt , die der Compiler sieht.Hier ist die Ausgabe dieses Copy-Paste:
Die Quellcodezeichen werden in dieser Reihenfolge gespeichert, und der Compiler behandelt sie als in dieser Reihenfolge, sie werden jedoch unterschiedlich angezeigt.
Beachten Sie das
\u202E
Zeichen, bei dem es sich um eine Überschreibung von rechts nach links handelt, das einen Block startet, in dem alle Zeichen von rechts nach links angezeigt werden müssen, und das Zeichen, bei dem es sich um eine Überschreibung von\u202D
links nach rechts handelt, bei dem ein verschachtelter Block beginnt, bei dem alle Zeichen angezeigt werden Zeichen werden in eine Reihenfolge von links nach rechts gezwungen, wobei die erste Überschreibung überschrieben wird.Ergo wird, wenn der ursprüngliche Code
class M
angezeigt wird, normal angezeigt, aber das\u202E
kehrt die Anzeigereihenfolge von allem von dort zu dem um\u202D
, wodurch alles wieder umgekehrt wird. (Formal wird alles vom\u202D
bis zum Zeilenendezeichen zweimal umgekehrt, einmal aufgrund des\u202D
und einmal, wobei der Rest des Textes aufgrund des umgekehrt\u202E
wird, weshalb dieser Text in der Mitte der Zeile statt am Ende angezeigt wird.) Die Direktionalität der nächsten Zeile wird aufgrund des Zeilenabschlusses unabhängig von der der ersten behandelt und wird daher{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
normal angezeigt.Den vollständigen (äußerst komplexen, Dutzende von Seiten langen) bidirektionalen Unicode-Algorithmus finden Sie im Unicode-Standardanhang Nr. 9 .
quelle
Aufgrund des bidirektionalen Unicode-Algorithmus sieht es anders aus . Es gibt zwei unsichtbare Zeichen von VKE und LRO, die der bidirektionale Unicode-Algorithmus verwendet, um das visuelle Erscheinungsbild der zwischen diesen beiden Metazeichen verschachtelten Zeichen zu ändern .
Das Ergebnis ist, dass sie visuell in umgekehrter Reihenfolge aussehen, die tatsächlichen Zeichen im Speicher jedoch nicht umgekehrt werden. Sie können die Ergebnisse analysieren hier . Der Java-Compiler ignoriert RLO und LRO und behandelt sie als Leerzeichen, weshalb der Code kompiliert wird.
Hinweis 1: Dieser Algorithmus wird von Texteditoren und Browsern verwendet, um Zeichen sowohl LTR-Zeichen (Englisch) als auch RTL-Zeichen (z. B. Arabisch, Hebräisch) gleichzeitig visuell anzuzeigen - daher "bi" -direktional. Weitere Informationen zum bidirektionalen Algorithmus finden Sie auf der Unicode- Website .
Anmerkung 2: Das genaue Verhalten von LRO und RLO ist in Abschnitt 2.2 des Algorithmus definiert.
quelle
M\u202E
unda\u202D
, aber diese Bezeichner scheinen als äquivalent zuM
und behandelt zu werdena
. (Das JLS erklärt dies nicht gut.)Der Charakter
U+202E
spiegelt den Code von rechts nach links, ist aber sehr clever. Ist ab dem M versteckt,Nun, als ich zuerst die Frage sah, die mir schwerfiel: "Es ist eine Art Witz, jemand anderem Zeit zu verlieren", aber dann öffnete ich meine IDE ("IntelliJ"), erstellte eine Klasse und übergab den Code ... und es kompiliert !!! Also schaute ich genauer hin und sah, dass die "öffentliche statische Leere" rückwärts war, also ging ich mit dem Cursor dorthin und löschte ein paar Zeichen ... Und was passiert? Die Zeichen wurden rückwärts gelöscht , also dachte ich, mmm ... selten ... ich muss es ausführen ... Also führe ich das Programm aus, aber zuerst musste ich es speichern ... und dann war ich es fand es! . Ich konnte die Datei nicht speichern, da meine IDE angab, dass für ein Zeichen eine andere Codierung vorhanden war, und zeigte mir, wo sie sich befandAlso starte ich in Google eine Recherche nach speziellen Zeichen, die den Job machen könnten, und das war's :)
Der bidirektionale Unicode-Algorithmus und die
U+202E
beteiligten erklären kurz :Warum einige Algorithmus wie schaffen das ?
quelle
Kapitel 3 der Sprachspezifikation enthält eine Erläuterung, indem detailliert beschrieben wird, wie die lexikalische Übersetzung für ein Java-Programm durchgeführt wird. Was für die Frage am wichtigsten ist:
Ein Programm ist also in Unicode-Zeichen geschrieben, und der Autor kann sie umgehen, indem
\uxxxx
er verwendet, falls die Dateicodierung das Unicode-Zeichen nicht unterstützt. In diesem Fall wird es in das entsprechende Zeichen übersetzt. Eines der in diesem Fall vorhandenen Unicode-Zeichen ist\u202E
. Es wird im Snippet nicht visuell angezeigt. Wenn Sie jedoch versuchen, die Codierung des Browsers zu ändern, werden möglicherweise versteckte Zeichen angezeigt.Daher führt die lexikalische Übersetzung zur Klassendeklaration:
was bedeutet, dass die Klassenkennung ist
M\u202E
. Die Spezifikation betrachtet dies als gültigen Bezeichner:quelle