El siguiente código produce la salida "¡Hola mundo!" (no, en serio, pruébalo).
public static void main(String... args) {
// The comment below is not a typo.
// \u000d System.out.println("Hello World!");
}
La razón de esto es que el compilador de Java analiza el carácter Unicode \u000d
como una nueva línea y se transforma en:
public static void main(String... args) {
// The comment below is not a typo.
//
System.out.println("Hello World!");
}
Por lo tanto, se "ejecuta" un comentario.
Dado que esto se puede utilizar para "ocultar" código malicioso o cualquier cosa que un programador malvado pueda concebir, ¿por qué está permitido en los comentarios ?
¿Por qué lo permite la especificación de Java?
La decodificación Unicode tiene lugar antes que cualquier otra traducción léxica. El beneficio clave de esto es que hace que sea trivial ir y venir entre ASCII y cualquier otra codificación. ¡Ni siquiera necesita averiguar dónde comienzan y terminan los comentarios!
Como se indica en la Sección 3.3 de JLS, esto permite que cualquier herramienta basada en ASCII procese los archivos fuente:
[...] El lenguaje de programación Java especifica una forma estándar de transformar un programa escrito en Unicode en ASCII que cambia un programa a una forma que pueda ser procesada por herramientas basadas en ASCII. [...]
Esto brinda una garantía fundamental para la independencia de la plataforma (independencia de los conjuntos de caracteres admitidos) que siempre ha sido un objetivo clave para la plataforma Java.
Poder escribir cualquier carácter Unicode en cualquier lugar del archivo es una característica interesante, y especialmente importante en los comentarios, cuando se documenta el código en idiomas no latinos. El hecho de que pueda interferir con la semántica de formas tan sutiles es solo un efecto secundario (desafortunado).
Hay muchas trampas en este tema y Java Puzzlers de Joshua Bloch y Neal Gafter incluyó la siguiente variante:
¿Es este un programa Java legal? Si es así, ¿qué imprime?
\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020\u0020 \u0063\u006c\u0061\u0073\u0073\u0020\u0055\u0067\u006c\u0079 \u007b\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020 \u0020\u0020\u0020\u0020\u0073\u0074\u0061\u0074\u0069\u0063 \u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028 \u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0020 \u0020\u0020\u0020\u0020\u0061\u0072\u0067\u0073\u0029\u007b \u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074 \u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0020 \u0022\u0048\u0065\u006c\u006c\u006f\u0020\u0077\u0022\u002b \u0022\u006f\u0072\u006c\u0064\u0022\u0029\u003b\u007d\u007d
(Este programa resulta ser un programa simple de "Hola mundo").
En la solución del rompecabezas, señalan lo siguiente:
Más en serio, este rompecabezas sirve para reforzar las lecciones de los tres anteriores: los escapes Unicode son esenciales cuando necesita insertar caracteres que no se pueden representar de ninguna otra manera en su programa. Evítelos en todos los demás casos.
Dado que esto aún no se ha abordado, aquí una explicación, por qué la traducción de los escapes Unicode ocurre antes de cualquier otro procesamiento de código fuente:
La idea detrás de esto era que permite traducciones sin pérdidas del código fuente de Java entre diferentes codificaciones de caracteres. Hoy en día, existe un soporte generalizado de Unicode, y esto no parece un problema, pero en ese entonces no era fácil para un desarrollador de un país occidental recibir un código fuente de su colega asiático que contiene caracteres asiáticos, haga algunos cambios ( incluyendo compilarlo y probarlo) y devolver el resultado, todo sin dañar algo.
Por lo tanto, el código fuente de Java se puede escribir en cualquier codificación y permite una amplia gama de caracteres dentro de identificadores, caracteres y String
literales y comentarios. Luego, para transferirlo sin pérdidas, todos los caracteres no admitidos por la codificación de destino son reemplazados por sus escapes Unicode.
Este es un proceso reversible y el punto interesante es que la traducción puede realizarse con una herramienta que no necesita saber nada sobre la sintaxis del código fuente de Java, ya que la regla de traducción no depende de ella. Esto funciona ya que la traducción a sus caracteres Unicode reales dentro del compilador también ocurre independientemente de la sintaxis del código fuente de Java. Implica que puede realizar una cantidad arbitraria de pasos de traducción en ambas direcciones sin cambiar el significado del código fuente.
Esta es la razón de otra característica extraña que ni siquiera se ha mencionado: la \uuuuuuxxxx
sintaxis:
Cuando una herramienta de traducción está escapando caracteres y encuentra una secuencia que ya es una secuencia escapada, debe insertar un adicional u
en la secuencia, convirtiendo \ucafe
a \uucafe
. El significado no cambia, pero cuando se convierte en la otra dirección, la herramienta solo debe eliminar una u
y reemplazar solo las secuencias que contienen una u
por sus caracteres Unicode. De esa manera, incluso los escapes Unicode se conservan en su forma original al realizar conversiones de ida y vuelta. Supongo que nadie usó esa función ...
Voy a agregar de manera completamente ineficaz el punto, solo porque no puedo ayudarme a mí mismo y aún no lo he visto hecho, que la pregunta no es válida ya que contiene una premisa oculta que es incorrecta, es decir, que el código está en ¡un comentario!
En Java, el código fuente \ u000d es equivalente en todos los sentidos a un carácter ASCII CR. Es un final de línea, simple y llanamente, donde sea que ocurra. El formato de la pregunta es engañoso, a qué corresponde sintácticamente esa secuencia de caracteres es:
public static void main(String... args) {
// The comment below is no typo.
//
System.out.println("Hello World!");
}
En mi humilde opinión, la respuesta más correcta es, por tanto: el código se ejecuta porque no está en un comentario; está en la siguiente línea. "Ejecutar código en comentarios" no está permitido en Java, tal como es de esperar.
Gran parte de la confusión se debe al hecho de que los resaltadores de sintaxis y los IDE no son lo suficientemente sofisticados como para tener en cuenta esta situación. O no procesan los escapes Unicode en absoluto, o lo hacen después de analizar el código en lugar de antes, como javac
hace.
El \u000d
escape finaliza un comentario porque los \u
escapes se convierten uniformemente a los caracteres Unicode correspondientes antes de que el programa sea tokenizado. Se podría utilizar igualmente \u0057\u0057
en lugar de //
a comenzar un comentario.
Este es un error en su IDE, que debe resaltar la sintaxis de la línea para dejar claro que \u000d
termina el comentario.
Esto también es un error de diseño en el idioma. No se puede corregir ahora, porque eso rompería los programas que dependen de él. \u
Los escapes deben ser convertidos al carácter Unicode correspondiente por el compilador solo en contextos donde eso "tenga sentido" (cadenas literales e identificadores, y probablemente en ningún otro lugar) o se les debería haber prohibido generar caracteres en el rango U + 0000–007F , o ambos. Cualquiera de esas semánticas habría evitado que el comentario terminara con el \u000d
escape, sin interferir con los casos en los que los \u
escapes son útiles; tenga en cuenta que eso incluye el uso de \u
escapes dentro de los comentarios como una forma de codificar los comentarios en una escritura no latina, porque el El editor de texto podría tener una visión más amplia de dónde los \u
escapes son importantes que el compilador. (Sin embargo, no conozco ningún editor o IDE que muestre los \u
escapes como los caracteres correspondientes en ningún contexto).
Hay un error de diseño similar en la familia C, 1 donde se procesa la barra invertida-nueva línea antes de que se determinen los límites de los comentarios, por ejemplo,
// this is a comment \
this is still in the comment!
Menciono esto para ilustrar que resulta fácil cometer este error de diseño en particular y no darse cuenta de que es un error hasta que es demasiado tarde para corregirlo, si está acostumbrado a pensar en la tokenización y analizar la forma en que piensan los programadores de compiladores. sobre tokenización y análisis. Básicamente, si ya ha definido su gramática formal y luego alguien presenta un caso especial sintáctico: trígrafos, barra invertida-nueva línea, codificación de caracteres Unicode arbitrarios en archivos fuente limitados a ASCII, lo que sea, eso debe encajar, es más fácil de agregue un pase de transformación antes del tokenizador que redefinir el tokenizador para prestar atención a dónde tiene sentido usar ese caso especial.
1 Para los pedantes: Soy consciente de que este aspecto de C fue 100% intencional, con la justificación, no lo estoy inventando, de que le permitiría forzar mecánicamente el código con líneas arbitrariamente largas en tarjetas perforadas. Seguía siendo una decisión de diseño incorrecta.
Esta fue una elección de diseño intencional que se remonta al diseño original de Java.
Para aquellas personas que preguntan "¿quién quiere escapes Unicode en los comentarios?", Supongo que son personas cuya lengua materna utiliza el conjunto de caracteres latinos. En otras palabras, es inherente al diseño original de Java que la gente pueda usar caracteres Unicode arbitrarios siempre que sea legal en un programa de Java, por lo general en comentarios y cadenas.
Podría decirse que es una deficiencia en los programas (como los IDE) utilizados para ver el texto fuente que dichos programas no pueden interpretar los escapes Unicode y mostrar el glifo correspondiente.
Estoy de acuerdo con @zwol en que esto es un error de diseño; pero soy aún más crítico con eso.
\u
escape es útil en literales de cadena y char; y ese es el único lugar donde debería existir. Debe manejarse de la misma manera que otros escapes como \n
; y "\u000A"
debería significar exactamente "\n"
.
No tiene absolutamente ningún sentido tener \uxxxx
comentarios, nadie puede leer eso.
Del mismo modo, no tiene sentido usarlo \uxxxx
en otra parte del programa. La única excepción es probablemente en las API públicas que están obligadas a contener algunos caracteres no ascii. ¿Cuál es la última vez que lo hemos visto?
Los diseñadores tuvieron sus razones en 1995, pero 20 años después, esta parece ser una elección incorrecta.
(pregunta a los lectores: ¿por qué esta pregunta sigue obteniendo nuevos votos? ¿Esta pregunta está vinculada desde algún lugar popular?)
Las únicas personas que pueden responder por qué se implementaron los escapes Unicode como estaban son las personas que escribieron la especificación.
Una razón plausible para esto es que existía el deseo de permitir el BMP completo como caracteres posibles del código fuente de Java. Sin embargo, esto presenta un problema:
Esto es increíblemente difícil cuando los fugas Unicode entran en juego: crea una gran cantidad de nuevas reglas de lexer.
La salida más fácil es hacer lexing en dos pasos: primero busque y reemplace todos los escapes Unicode con el carácter que representa, y luego analice el documento resultante como si los escapes Unicode no existieran.
La ventaja de esto es que es fácil de especificar, por lo que simplifica la especificación y es fácil de implementar.
La desventaja es, bueno, tu ejemplo.
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Si este tráiler de pesadilla de la temporada más reciente de Great British Bake Off te asustó y te hizo no volver a ver el programa, es posible que tengas suerte: PBS no ha decidido si se transmitirá o no la última temporada en los Estados Unidos. actualización, para aquellos que no siguen sin aliento este tipo de drama de nicho: el presentador Paul Hollywood y la hermosa carpa llena de batidoras de colores pastel y cuadros se trasladaron de la BBC al Canal 4; Mary Berry, Sue Perkins y Mel Giedroyc renunciaron.
Foto: Netflix Oh, Hello On Broadway (Netflix): Después de llegar a Broadway el año pasado, los dos locos del Upper West Side interpretados por John Mulaney y Nick Kroll finalmente llegaron a Netflix. El especial consta del espectáculo en el escenario, algunos momentos entre bastidores y un invitado muy especial de “Too Much Tuna”.
¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.