Aquí hay un código que encontré en Internet:
class M{public static void main(String[]a){System.out.print(new char[]
{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
Este código se imprime Hello World!
en la pantalla; Puedes verlo correr aquí . Puedo ver claramente public static void main
escrito, pero está al revés. ¿Cómo funciona este código? ¿Cómo se compila esto?
Editar: probé este código en IntellIJ, y funciona bien. Sin embargo, por alguna razón no funciona en notepad ++, junto con cmd. Todavía no he encontrado una solución para eso, así que si alguien lo hace, comente a continuación.
java
unicode
right-to-left
Calabaza imaginaria
fuente
fuente
M
y también después[]a
: fileformat.info/info/unicode/char/202d/index.htm Se llama OVERRIDE DE IZQUIERDA A DERECHAniam diov citats cilbup
suena como un proverbio latino ..Respuestas:
Aquí hay caracteres invisibles que alteran la forma en que se muestra el código. En Intellij, estos se pueden encontrar copiando y pegando el código en una cadena vacía (
""
), que los reemplaza con escapes Unicode, eliminando sus efectos y revelando el orden que ve el compilador.Aquí está la salida de ese copiar y pegar:
Los caracteres del código fuente se almacenan en este orden, y el compilador los trata como si estuvieran en este orden, pero se muestran de manera diferente.
Tenga en cuenta que el
\u202E
carácter, que es una anulación de derecha a izquierda, comienza un bloque donde todos los caracteres están obligados a mostrarse de derecha a izquierda, y el\u202D
, que es una anulación de izquierda a derecha, inicia un bloque anidado donde todos los caracteres se fuerzan en orden de izquierda a derecha, anulando la primera anulación.Ergo, cuando muestra el código original,
class M
se muestra normalmente, pero\u202E
invierte el orden de visualización de todo, desde allí hasta el\u202D
, lo que invierte todo nuevamente. (Formalmente, todo, desde el\u202D
terminador de línea hasta el reverso, se invierte dos veces, una vez debido al\u202D
y el resto del texto invertido debido a la\u202E
, por lo que este texto aparece en el medio de la línea en lugar del final). La direccionalidad de la línea siguiente se maneja independientemente de la primera debido al terminador de línea, por lo que{'H','e','l','l','o',' ','W','o','r','l','d','!'});}}
se muestra normalmente.Para el algoritmo bidireccional Unicode completo (extremadamente complejo, decenas de páginas de largo), consulte el Anexo 9 estándar de Unicode .
fuente
Se ve diferente debido al Algoritmo bidireccional Unicode . Hay dos caracteres invisibles de RLO y LRO que el Algoritmo bidireccional Unicode usa para cambiar la apariencia visual de los caracteres anidados entre estos dos metacaracteres.
El resultado es que visualmente se ven en orden inverso, pero los caracteres reales en la memoria no se invierten. Puedes analizar los resultados aquí . El compilador de Java ignorará RLO y LRO, y los tratará como espacios en blanco, razón por la cual el código se compila.
Nota 1: los editores de texto y los navegadores utilizan este algoritmo para mostrar visualmente los caracteres, tanto los caracteres LTR (inglés) como los caracteres RTL (p. Ej., Árabe, hebreo) juntos al mismo tiempo, por lo tanto, "bi" -direccional. Puede leer más sobre el algoritmo bidireccional en el sitio web de Unicode .
Nota 2: El comportamiento exacto de LRO y RLO se define en la Sección 2.2 del Algoritmo.
fuente
M\u202E
ya\u202D
, pero esos identificadores parecen tratarse como equivalentes aM
ya
. (El JLS no hace un buen trabajo al explicar esto.)El personaje
U+202E
refleja el código de derecha a izquierda, aunque es muy inteligente. Está oculto a partir de la M,Bueno, al principio cuando vi la pregunta, dije: "es una especie de broma, perder el tiempo de alguien más", pero luego abrí mi IDE ("IntelliJ"), creé una clase y pasé el código ... y se compiló !!! Entonces, miré mejor y vi que el "vacío estático público" estaba al revés, así que fui allí con el cursor y borré algunos caracteres ... ¿Y qué sucede? Los caracteres comenzaron a borrarse hacia atrás , así que pensé mmm ... raro ... tengo que ejecutarlo ... Así que procedo a ejecutar el programa, pero primero tenía que guardarlo ... y fue entonces cuando ¡Lo encontré! . No pude guardar el archivo porque mi IDE decía que había una codificación diferente para algunos caracteres, y me indicó dónde estaba, Así que empiezo una investigación en Google de caracteres especiales que podrían hacer el trabajo, y eso es todo :)
el algoritmo bidireccional de Unicode, e
U+202E
involucrado, explica brevemente :¿Por qué crear un algoritmo como este ?
fuente
El Capítulo 3 de la especificación del lenguaje proporciona una explicación al describir en detalle cómo se realiza la traducción léxica para un programa Java. Lo más importante para la pregunta:
Entonces, un programa está escrito en caracteres Unicode, y el autor puede escapar de ellos usando
\uxxxx
en caso de que la codificación del archivo no sea compatible con el carácter Unicode, en cuyo caso se traduce al carácter apropiado. Uno de los caracteres Unicode presentes en este caso es\u202E
. No se muestra visualmente en el fragmento, pero si intenta cambiar la codificación del navegador, pueden aparecer los caracteres ocultos.Por lo tanto, la traducción léxica da como resultado la declaración de clase:
lo que significa que el identificador de clase es
M\u202E
. La especificación considera esto como un identificador válido:fuente