Voici un code que j'ai trouvé sur Internet:
class M{public static void main(String[]a){System.out.print(new char[]
{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
Ce code s'imprime Hello World!
sur l'écran; vous pouvez le voir fonctionner ici . Je peux voir clairement public static void main
écrit, mais c'est à l'envers. Comment fonctionne ce code? Comment cela compile-t-il même?
Edit: J'ai essayé ce code dans IntellIJ, et cela fonctionne très bien. Cependant, pour une raison quelconque, cela ne fonctionne pas dans notepad ++, avec cmd. Je n'ai toujours pas trouvé de solution à cela, donc si quelqu'un le fait, commentez ci-dessous.
java
unicode
right-to-left
Citrouille imaginaire
la source
la source
M
et aussi après[]a
: fileformat.info/info/unicode/char/202d/index.htm Ça s'appelle LEFT-TO-RIGHT OVERRIDEniam diov citats cilbup
sonne comme un proverbe latin ..Réponses:
Il y a des caractères invisibles ici qui modifient la façon dont le code est affiché. Dans Intellij ceux-ci peuvent être trouvés en copiant-collant le code dans une chaîne vide (
""
), qui les remplace par des échappements Unicode, supprimant leurs effets et révélant l'ordre que le compilateur voit.Voici la sortie de ce copier-coller:
Les caractères du code source sont stockés dans cet ordre et le compilateur les traite comme étant dans cet ordre, mais ils s'affichent différemment.
Notez le
\u202E
caractère, qui est un remplacement de droite à gauche, en commençant un bloc où tous les caractères sont forcés d'être affichés de droite à gauche, et le\u202D
, qui est un remplacement de gauche à droite, en commençant un bloc imbriqué où tous les caractères sont forcés dans un ordre de gauche à droite, remplaçant le premier remplacement.Ergo, lorsqu'il affiche le code d'origine,
class M
s'affiche normalement, mais l'\u202E
inverse l'ordre d'affichage de tout de là vers le\u202D
, qui inverse à nouveau tout. (Formellement, tout depuis le\u202D
terminateur de ligne est inversé deux fois, une fois en raison de la\u202D
et une fois avec le reste du texte inversé en raison de la\u202E
, c'est pourquoi ce texte apparaît au milieu de la ligne au lieu de la fin.) La directionnalité de la ligne suivante est gérée indépendamment de la première en raison du terminateur de ligne, elle{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
est donc affichée normalement.Pour l'algorithme bidirectionnel Unicode complet (extrêmement complexe, des dizaines de pages de long), voir l' Annexe # 9 de la norme Unicode .
la source
Il semble différent en raison de l' algorithme bidirectionnel Unicode . Il y a deux caractères invisibles de RLO et LRO que l'algorithme bidirectionnel Unicode utilise pour changer l' apparence visuelle des caractères imbriqués entre ces deux métacaractères.
Le résultat est que visuellement ils regardent dans l'ordre inverse, mais les caractères réels en mémoire ne sont pas inversés. Vous pouvez analyser les résultats ici . Le compilateur Java ignorera RLO et LRO et les traitera comme des espaces, c'est pourquoi le code se compile.
Remarque 1: Cet algorithme est utilisé par les éditeurs de texte et les navigateurs pour afficher visuellement les caractères à la fois les caractères LTR (anglais) et RTL (par exemple l'arabe, l'hébreu) en même temps - d'où le sens "bi". Vous pouvez en savoir plus sur l'algorithme bidirectionnel sur le site Web d'Unicode .
Remarque 2: Le comportement exact de LRO et RLO est défini dans la section 2.2 de l'algorithme.
la source
M\u202E
eta\u202D
, mais ces identifiants semblent être traités comme équivalents àM
eta
. (Le JLS ne fait pas un bon travail pour expliquer cela.)Le personnage
U+202E
reflète le code de droite à gauche, il est cependant très intelligent. Est caché à partir du M,Eh bien, au début, quand j'ai vu la question que je tenais, "c'est une sorte de blague, perdre du temps à quelqu'un d'autre", mais ensuite, j'ai ouvert mon IDE ("IntelliJ"), créé une classe et passé le code ... et il a compilé !!! Alors, j'ai jeté un coup d'œil et j'ai vu que le "vide statique public" était en arrière, alors je suis allé là-bas avec le curseur, et j'ai effacé quelques caractères ... Et que se passe-t-il? Les caractères ont commencé à s'effacer vers l'arrière , donc, je pensais que mmm .... rare ... Je dois l'exécuter ... Alors je continue à exécuter le programme, mais d'abord je devais l' enregistrer ... et c'est à ce moment que j'ai je l'ai trouvé! . Je n'ai pas pu enregistrer le fichier parce que mon IDE a dit qu'il y avait un codage différent pour certains caractères, et pointez-moi où était-il, Donc je commence une recherche dans Google pour les caractères spéciaux qui pourraient faire le travail, et c'est tout :)
l'algorithme bidirectionnel Unicode, et
U+202E
impliqué, expliquer brièvement :Pourquoi créer un algorithme comme celui-ci ?
la source
Le chapitre 3 de la spécification du langage fournit une explication en décrivant en détail comment la traduction lexicale est effectuée pour un programme Java. Ce qui compte le plus pour la question:
Un programme est donc écrit en caractères Unicode, et l'auteur peut y échapper en utilisant
\uxxxx
dans le cas où l'encodage de fichier ne prend pas en charge le caractère Unicode, auquel cas il est traduit au caractère approprié. L'un des caractères Unicode présents dans ce cas est\u202E
. Il n'est pas affiché visuellement dans l'extrait de code, mais si vous essayez de changer l'encodage du navigateur, les caractères masqués peuvent apparaître.Par conséquent, la traduction lexicale se traduit par la déclaration de classe:
ce qui signifie que l'identifiant de classe est
M\u202E
. La spécification considère cela comme un identifiant valide:la source