Pourquoi l'exécution de code Java dans les commentaires avec certains caractères Unicode-ils autorisés?
Le code suivant génère la sortie "Bonjour le Monde!" (non, vraiment, essayez).
public static void main(String... args) {
//The comment below is not a typo.
//\u000d System.out.println("Hello World!");
}
La raison pour cela est que le compilateur Java analyse le caractère Unicode \u000d
comme une nouvelle ligne et se transforme en:
public static void main(String... args) {
//The comment below is not a typo.
//
System.out.println("Hello World!");
}
Résultant ainsi en un commentaire d'être "exécuté".
Car il peut être utilisé pour "masquer" le code malveillant ou que ce soit un mauvais programmeur la possibilité de concevoir, pourquoi est-il permis, dans les commentaires?
Pourquoi est-ce autorisé par les spécifications de Java?
- "Pourquoi est-ce autorisé" semble être trop opinion de moi. La langue concepteurs pris une décision, quoi d'autre est-il besoin de le savoir? Sauf si vous trouvez une déclaration de la personne qui fait de cette décision, nous ne pouvons que spéculer.
- Bien qu'étrange, je ne vois pas cela comme un problème réel. Les utilisateurs normaux ne savent pas la différence entre le code caché dans un commentaire et régulière code pour eux, il n'a pas d'importance. Ensuite, il pourrait être un membre de l'équipe de cacher le code des autres membres, mais les développeurs vont réagir en voyant un étrange commentaire comme celui-ci, et de le supprimer ou étudier. Si c'était pour passer à travers et mis en usage, un VCS va vous dire la personne qui l'a fait, donc on peut attraper.
\u000d
signifie ASCII0x0D
,\n
,New Line
- Une chose intéressante, c'est au moins que OP IDE évidemment est faux et affiche une coloration incorrecte,
- C'est expliqué dans la question. L'OP est de se demander pourquoi dans la section des commentaires, il est également traduite
\n
. - Peut-être liés: stackoverflow.com/questions/4448180/...
- Oui, la réponse faisant autorité ne peut venir que de créateurs. Cependant, il peut y avoir de l'information quelque part sur pourquoi cela a été fait (compatibilité, la limitation des outils, etc.), donc il est responsable.
- cela ne convient pas pour une bonne cause ou pour une question comme par AFIN de normes.Si vous voyez de près le 1er vote de proximité a été fait par tjcrowder qui est d'avoir 360,349 reps
- 'cause caractère de saut de ligne est également autorisé ... je l'avais testé avec c++ et c#, ces langues sont skiping les lignes après la lecture de // mais java semble analyse la ligne complète et interpréter le code de saut de ligne char.
- Mais les concepteurs de Java visitez DONC il est donc possible d'obtenir des réponses par l'un d'eux. Ils peuvent aussi existent des ressources qui déjà répondre à cette question.
- Je ne sais pas pour vous, mais je soupçonne que c'est juste un effet secondaire de la décision générale pour traiter unidoce caractères à l'intérieur de commentaires. Peut-être afin de permettre les commentaires de code en langues étrangères, ou avec de la mathématique grecque signes. Personnellement, je préfère l'éviter... (javadoc peut-être une exception, mais ensuite je n'ai pas besoin de cette fonction parce que le HTML a son propre support pour les caractères spéciaux).
- stackoverflow.com/questions/3866187/... exemple amusant
- Unicode d'échappement partout et sont toujours analysées avant tout le reste. L'intention est que tout fichier source peut être converti en équivalent fichier contenant uniquement des caractères ASCII.
- Connexes: stackoverflow.com/q/13116648/319403
- C'est également affiché comme un commentaire dans Eclipse, donc, connaissez-vous une IDE qui n' pas l'afficher comme un commentaire?
- Netbeans (au moins dans la version 8.0.2) se termine le commentaire après l'echappé Unicode retour à la ligne, montrant la
println()
comme du code. Il montre également le même comportement que le compilateur pour l'échappé de début de commentaire le code de stackoverflow.com/questions/4448180/... - Cela signifie également que les invalides Unicode s'échappe dans les commentaires de provoquer des erreurs de compilation (comme un chemin d'accès windows continue
\users
), ce qui peut être gênant. - Les OP n'ont pas fait mention de son IDE affiche que le code. La seule chose, en soulignant que nous pouvons dire à partir de texte de la question est que le code Java surligneur ici, DONC s'il se trompe.
- Ce que vous montrez est un bug dans l'IDE. Il est parfaitement valable code. Que l'IDE ne pas MONTRER que le code est le bug. IDEs faut arrêter de croire les compilateurs ne sont pas conscients de l'unicode.
- ce qui fait de vous tirer la conclusion que c'est un bug dans l'OP de l'IDE? (Comment savez-vous OP est d'utiliser un IDE?)
- La réponse simple est que le code n'est pas dans un commentaire à tous, par les règles de la langue, de sorte que la question est mal formé.
- Eclipse Luna se termine le commentaire après l'unicoded retour chariot. Son comportement par défaut est de "résoudre" le caractère unicode lors de l'enregistrement du document, de sorte que tout le code écrit dans un commentaire après une unicode retour chariot sera fait de montrer à l'extérieur de la ligne de commentaire.
- peut-être en utilisant le terme IDE est présomptueux. L'erreur est dans l'éditeur/IDE/ou de la perception de l'utilisateur de la "ligne" et "déclaration". La perception de l'utilisateur d'un relevé actif peut être considérablement améliorée par l'utilisation d'une syntaxe conscient de l'éditeur. Si la syntaxe de conscience de l'éditeur de ne pas gérer correctement un aspect de la prise en charge syntaxe du langage, l'outil est dans l'erreur, vis-a-vis, c'est un bug.
- C'est DONC de la coloration syntaxique, bien sûr, ne sait pas qu'elle ne traite qu'avec Java. C'est un "jack of all trades", et il est lié à la promenade sur le bord des cas.
- Avoir une quantité massive de rep comme ça ne signifie pas qu'ils ont un avis autorisé que tout le monde devrait suivre. Bien que le libellé de la question qui peut changer (le"pourquoi" est très opiniâtre) je pense que c'est vraiment un très bon sujet, et je suis très content que ça été apportée jusqu'ici.
- Un raisonnablement intelligent malfaiteur aurait assurez-vous qu'il ressemblait à une partie du commentaire. Ne devrait pas être difficile de le faire paraître innocent.
- En supposant que ce n'est pas un bug du compilateur, je dirais que c'est une grave et choquant faille dans la spec. Employés malveillants existent, et ils sont assez dangereux sans la langue en les aidant à ce point.
- Vous pouvez réellement commentaire de l'ensemble de la classe avec ce truc et il fonctionne toujours!
- La question du titre semble être faux pour moi. L' \u000d personnage est dans ce cas de résiliation du commentaire, donc le code n'est pas dans un commentaire à tous. C'est aussi absurde que de demander ton le compilateur analyse le caractère de saut de ligne à la fin du commentaire, plutôt que d'aller à l'infini. En fin de compte ce défaut provient du défaut inhérent de faire des commentaires de la ligne de base dans un non la ligne de base de la langue.
- C'est l'ensemble de la prémisse de la question, n'est-ce pas?
- Shameless plug: Vous pouvez jouer avec cela à l': obfuscat.ion.la terre
\u000d
est le retour chariot;\u000a
serait le retour à la ligne. L'un d'eux termine le//
commentaire.- Double Possible de unicode caractère de saut de ligne(\u000d) en Java
- Je vais voter pour fermer cette question hors-sujet, car la question est sur la langue, de la conception, pas de programmation à proprement parler.
- Je vais voter pour fermer cette question hors-sujet, car l'erreur ne peut pas être recréé. Le code n'est pas un commentaire, cependant, l'IDE de l'OP choses, il est, mais que c'est un bug dans l'IDE et a peu à voir avec le fait que vous pouvez exécuter du code dans un commentaire
- Pourquoi le compilateur accepte \u-séquences à l'extérieur de la chaîne/les chaînes de caractères? Ainsi, au premier coup d'œil, il semblait être une bonne idée. Avec le recul, nous pouvons dire qu'il n'était pas une bonne idée, mais il est trop tard. (Remarque: il existe de nombreuses mentions de "IDE" dans les commentaires, mais la question n'a rien à voir avec une quelconque "IDE".)
- Le point de permettre à de code UTF-16 unité s'échappe est de soutenir tous les valide Java identificateurs (esp. les noms de classe) dans un fichier source avec un encodage de caractère qui ne l'est pas.
Vous devez vous connecter pour publier un commentaire.
Unicode décodage prend place avant les autres lexical de la traduction. Le principal avantage de cela est qu'il est trivial de faire l'aller-retour entre ASCII et un autre codage. Vous n'avez même pas besoin de savoir où les commentaires de début et de fin!
Comme indiqué dans JLS Section 3.3 cela permet à tout basé sur le code ASCII outil pour traiter les fichiers source:
Cela donne une garantie fondamentale pour l'indépendance de plate-forme (indépendance de prise en charge des jeux de caractères) qui a toujours été un objectif majeur pour la plate-forme Java.
Être capable d'écrire n'importe quel caractère Unicode n'importe où dans le fichier est une fonction propre, et particulièrement important dans les commentaires, lors de la fixation de code dans des langues non latines. Le fait qu'il peut interférer avec la sémantique de telle manière subtile est juste une (malheureuse) d'effets secondaires.
Il y a de nombreux pièges sur ce thème et Java casse-têtes par Joshua Bloch et Neal Gafter inclus la variante suivante:
(Ce programme s'avère être un simple "Hello World" du programme.)
Dans la solution à la devinette, ils soulignent:
Source: Java: Exécution de code dans les commentaires?!
\u000d
et la partie après il devrait avoir le code de faits saillants.// C:\user\...
ce qui conduit à une erreur de compilation puisque\user
n'est pas valide séquence d'échappement Unicode.\u000d
est mis en évidence en partie. Après avoir appuyé sur Ctrl+Maj+F le personnage est remplacée par la nouvelle ligne et le reste de la ligne est emballé\u000d
est interprété comme un caractère de nouvelle ligne.\u002A/
devrait mettre fin à la commenter.\u002A/
est vraiment mal, éclipse totalement ne parvient pas à analyser. Mettre le code entre/*\u002A/
et/\u002a*/
et il est complètement caché comme commentaire. Trouvé ce que bug 3533\u
notation pour représenter quoi que ce soit représentable en ASCII.{}
\u
échappe pour quelque chose d'aussi omniprésents que les accolades...string st="Hello\u000D\u000Athere"
serait de générer des douze chaîne de caractères contenant un retour chariot et une nouvelle ligne.LRM
de caractère vous permettra de compiler du code tel quefor (char c = 1; c > 0; c++)
Depuis, il n'a pas encore été examinés, ici une explication, pourquoi la traduction de l'Unicode des évasions qui se passe avant tout autre code source de traitement:
L'idée derrière cela est qu'il permet lossless traductions de code source Java entre les différents encodages de caractères. Aujourd'hui, il existe un large support de l'Unicode, et ça ne ressemble pas à un problème, mais à l'époque, il n'était pas facile pour un développeur d'un pays occidental à recevoir certains le code source de ses collègues Asiatiques contenant des caractères Asiatiques, apporter des modifications (y compris la compilation et les tests) et d'envoyer le résultat à l'arrière, tous sans endommager quelque chose.
Ainsi, le code source de Java peut être écrit dans n'importe quel encodage et permet un large éventail de caractères à l'intérieur d'identifiants, de caractère et de
String
littéraux et les commentaires. Puis, afin de les transférer sans perte, tous les caractères non pris en charge par la cible de codage sont remplacés par leur Unicode échappe.C'est un processus réversible et le point intéressant est que la traduction peut être faite par un outil qui n'a pas besoin de savoir quelque chose sur le code source Java syntaxe que la traduction de la règle n'est pas dépendant de lui. Cela fonctionne de la traduction à leurs caractères Unicode à l'intérieur du compilateur qui se passe de manière indépendante pour le code source Java syntaxe. Cela implique que vous pouvez effectuer un nombre arbitraire de pas de traduction dans les deux sens sans jamais en modifier la signification du code source.
C'est la raison pour une autre bizarre fonctionnalité qui n'a même pas été mentionné: le
\uuuuuuxxxx
syntaxe:Lorsqu'un outil de traduction est d'échapper les caractères et de rencontres, une séquence qui est déjà évadé de la séquence, il doit insérer un
u
dans la séquence, la conversion de\ucafe
à\uucafe
. Le sens ne change pas, mais lors de la conversion dans l'autre sens, l'outil doit juste enlever unu
et de ne remplacer que les séquences contenant un seulu
par leurs caractères Unicode. De cette façon, même Unicode évasions sont conservés dans leur forme originale lors de la conversion d'avant en arrière. Je suppose, personne n'a jamais utilisé cette fonctionnalité...native2ascii
ne semble pas utiliser le\uu...xxxx
syntaxe,native2ascii
était destiné à contribuer à la préparation des offres de ressources en les convertissant en iso-latin-1, tel queProperties.load
a été fixé à lire en latin-1 seulement. Et là, les règles sont différentes, pas de\uuu…
syntaxe et aucun début de l'étape de traitement. Dans les fichiers de propriétés,property=multi\u000aline
est en effet le même queproperty=multi\nline
. (Contredisant le membre de phrase “à l'aide d'Unicode s'échappe tel que défini à la section 3.3 de La Java™ Spécification de Langage” de la documentation)\u
échappe à produire les caractères U+0000–007F gamme. (Tous ces caractères peuvent être représentés de façon native par tous les nationaux que les codages ont été pertinents dans les années 1990—eh bien, peut-être à l'exception de certains des caractères de contrôle, mais vous n'avez pas besoin d'écrire de Java, de toute façon.)Je vais complètement inefficace ajouter le point, juste parce que je ne peux pas m'en empêcher et je n'en ai pas vu encore, que la question n'est pas valide car il contient un caché, postulat qui est faux, à savoir que le code est dans un commentaire!
Dans le code source de Java \u000d est équivalent dans tous les sens pour un ASCII caractère CR. C'est une fin de ligne, simple et clair, partout où il se produit. La mise en forme de la question est trompeuse, en ce que la séquence de caractères effectivement du point de vue syntaxique correspond est:
À mon humble avis le plus de la réponse correcte est donc: le code s'exécute, car il n'est pas dans un commentaire, c'est sur la ligne suivante. "L'exécution de code dans les commentaires" n'est pas autorisé en Java, tout comme vous pouvez attendre.
Grande partie de la confusion vient du fait que la syntaxe de surligneurs et IDEs ne sont pas assez sophistiqués pour tenir compte de cette situation. Ils ne traitent pas l'unicode échappe à tous, ou ils le font après l'analyse du code au lieu de l'avant, comme
javac
n'.La
\u000d
échapper termine un commentaire parce que\u
les fuites sont uniformément converti à la correspondante de caractères Unicode avant le programme est sous forme de jeton. Vous pourriez également utiliser\u0057\u0057
au lieu de//
à commencer un commentaire.C'est un bug dans votre IDE, qui devrait de la syntaxe en surbrillance la ligne à, il est clair que la
\u000d
se termine le commentaire.C'est aussi une erreur de conception dans la langue. Il ne peut pas être corrigé maintenant, parce que ce serait briser les programmes qui en dépendent.
\u
échappe devrait être converti à caractère Unicode correspondant par le compilateur seulement dans des contextes où les qui "fait sens" (chaîne de caractères littéraux et les identifiants, et probablement nulle part ailleurs) ou qu'ils doivent avoir été interdit de produire les caractères U+0000–007F gamme, ou les deux. L'une de ces sémantique aurait empêché le commentaire ne soit interrompue par la\u000d
échapper, sans interférer avec les cas où\u
d'échappement utile de noter que cette comprend utilisation de\u
échappe à l'intérieur des commentaires comme une façon d'encoder les commentaires dans un non-latins, parce que l'éditeur de texte pourrait prendre une vue plus large de l'endroit où\u
les fuites sont importantes que le compilateur ne. (Je ne suis pas au courant de tout éditeur ou IDE qui permettra d'afficher\u
s'échappe comme les caractères correspondants dans tout contexte, cependant).Il y a une semblable erreur de conception dans le C de la famille,1 où backslash-retour à la ligne est traitée avant le commentaire limites sont définies, si par exemple la
Je soulève cette question pour illustrer que c'est facile de faire cette erreur de conception, et ne pas réaliser que c'est une erreur, jusqu'à ce qu'il soit trop tard pour le corriger, si vous êtes habitué à la réflexion sur la segmentation et l'analyse de la façon dont le compilateur les programmeurs pensent la segmentation et l'analyse. En gros, si vous avez déjà défini votre grammaire formelle et puis quelqu'un arrive avec un syntaxiques cas particulier — trigraphs, barre oblique inverse-saut de ligne, le codage arbitraire de caractères Unicode dans les fichiers source limitée au format ASCII, ce qui doit être calé dans, il est plus facile d'ajouter une transformation passer avant le tokenizer que c'est de redéfinir le tokenizer de prêter attention à l'endroit où il est logique d'utiliser ce cas particulier.
1 Pour les pédants: je suis conscient que cet aspect de la C était de 100% intentionnelle, avec justification à l'appui — que je ne fais pas ce que ça permettrait de mécanique de la force de l'ajustement de code avec arbitrairement long des lignes sur des cartes perforées. C'est encore une erreur de conception de décision.
!
) devrait avoir indiqué que le reste de la ligne physique doit être ignorée, et le premier caractère de la ligne suivante doit être considérée comme directement suivant le caractère avant la barre oblique inverse. Qui permettrait\!
à coups de poing dans les colonnes 71-72, laissant les huit colonnes disponibles pour les numéros de séquence. Dans certains contextes, le marqueur-bande truc pourrait réduire la nécessité lisibles par machine pour les numéros, mais je ne pense pas qu'il serait l'éliminer.\u
est moins absurde que la décision de suivre C du plomb dans l'aide de zéros pour la notation octale. Tout en octal notation est parfois utile, je n'ai pas encore entends quelqu'un qui s'articulent autour d'un argument pourquoi un zéro est une bonne façon de le mentionner.\u
que la pré-segmentation en unités de transformation si il était interdit de produire des caractères U+0000..U+007F gamme. C'est la combinaison de "cela fonctionne partout" et "cet alias de caractères ASCII avec syntaxique signification" qui rétrograde à partir maladroit de flat-out faux.Foo
est définie à l'extérieur de son contexte etfoo
est définie dans un intérieur, puis à l'intérieur de la contextefoo
ferait référence à la dernière identifiant etFoo
serait une erreur de syntaxe. L'application d'une telle règle de homoglyphs, mais avec un moyen de la contourner dans des cas particuliers...foo
etFoo
, ouΧ
etX
, à la fois d'être accessible ici), permettrait de se prémunir contre beaucoup de situations ambiguës.i
àI
et quand quelqu'un compile sur un turc locale,i
est soudain résolu àİ
...Six
a été défini, les identifiantssix
,SİX
,Sıx
, etc. ne serait pas utilisable, même si elles existaient dans des étendues extérieures. Les Collisions peuvent entraîner des erreurs de syntaxe qui nécessitent un explicite "distinguer ces identifiants" directive, mais ne pouvait pas changer le sens de code qui toujours compilé.//
commentaire sur une seule ligne n'existe pas. Et depuis C est un terminateur d'instruction qui n'est pas une nouvelle ligne, il serait principalement utilisé pour les longues chaînes, sauf que, autant que je puisse en déterminer la "chaîne de caractères littérale de concaténation de" est il y a de K&R.C'était intentionnel choix de conception qui va tout le chemin du retour à l'origine de la conception de Java.
À ces gens qui demandent "qui veut Unicode s'échappe dans les commentaires?", Je présume qu'ils sont des gens dont la langue maternelle utilise les caractères latins. En d'autres termes, il est inhérent à la conception originale de Java que les gens pourraient utiliser arbitraire de caractères Unicode où juridique dans un programme Java, le plus souvent dans les commentaires et les chaînes de caractères.
C'est sans doute une lacune dans les programmes (comme Ide) utilisée pour afficher le texte source que de tels programmes ne peuvent pas interpréter l'Unicode s'échappe et afficher le glyphe.
Je suis d'accord avec @zwol que ceci est une erreur; mais je suis encore plus critique.
\u
escape est utile dans le string et char littéraux; et c'est le seul endroit où il devrait exister. Il devrait être traité de la même manière que les autres s'échappe comme\n
; et"\u000A"
devrait dire exactement"\n"
.Il n'y a absolument aucun point d'avoir
\uxxxx
dans les commentaires - personne ne peut le lire.De même, il n'y a aucun point de l'utilisation de
\uxxxx
dans l'autre partie du programme. La seule exception est probablement dans les Api publiques qui sont contraints à contenir certaines non-ascii les caractères - quelle est la dernière fois que nous avons vu que?Les concepteurs avaient leurs raisons en 1995, mais 20 ans plus tard, ce qui semble être un mauvais choix.
(question pour les lecteurs - pourquoi cette question reçois des nouvelles des votes? cette question est liée à partir de quelque part populaire?)
int \u5431
quand vous pouvez faireint 整
UTF-8
soutien en 1995). Vous avez juste à appeler une méthode et ne souhaitez pas installer le support des langues Asiatiques pack de votre système d'exploitation (rappelez-vous, les années nonante) pour cette seule méthode...ä
etä
sont des identifiants différents (parce que l'on estU+0061U+0308
et les autresU+00E4
).%n
dansformat()
.\n
signifie exactement le caractère0x0a
, voir docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6⪹
-> ⪹class Løtveit
au lieu declass L\u00D8tveit
@HaakonLøtveit
, l'éditeur n'a pour moi par l'auto-complétion. Même pour Java. Même si je dois copierø
, il est probablement plus facile que de trouver et de taper son unicode.Les seules personnes qui peuvent répondre à pourquoi Unicode évasions ont été mises en œuvre comme ils l'ont été sont les personnes qui ont écrit la spécification.
Une raison plausible c'est qu'il y a la volonté de permettre à l'ensemble de la BMP que possible les caractères de code source Java. Cela pose un problème cependant:
C'est incroyablement difficile lors de l'Unicode échappe à entrer dans la mêlée: il crée un ensemble de charge de nouveaux lexer règles.
Le chemin le plus facile est de faire lexing en deux étapes: la première est de rechercher et de remplacer les caractères Unicode s'échappe avec le personnage qu'il représente, et ensuite d'analyser le document qui en résulte comme si Unicode échappe n'existent pas.
L'avantage, c'est qu'il est facile de spécifier, de sorte qu'il rend la spécification plus simple, et il est facile à mettre en œuvre.
L'inconvénient est, bien, votre exemple.
Le compilateur ne concerne pas seulement traduit Unicode s'échappe dans les personnages qu'ils représentent avant qu'il traite un programme en jetons, mais il le fait avant de jeter les commentaires et les espaces.
Ce programme contient un seul échappement Unicode (\u000d), situé dans son seul commentaire. Comme le commentaire que vous avez dit, cette évasion représente le caractère de saut de ligne, et le compilateur dûment traduit avant de le jeter commentaire.
C'est dépend de la plateforme. Sur certaines plateformes, comme UNIX, il va travailler; sur d'autres, tels que Windows, il ne sera pas. Bien que la sortie peut regarder la même chose à l'œil nu, on pourrait facilement causer des problèmes si elle a été enregistré dans un fichier ou transmise à un autre programme pour un traitement ultérieur.
\u000d
que la fin d'une ligne//
commentaire, même sur Windows. (Testé avec Oracle Java 1.7 et IBM Java 1.8 sur Windows 7, juste pour être sûr...)