特定の Unicode 文字を含むコメント内で Java コードの実行が許可されるのはなぜですか? 質問する

特定の Unicode 文字を含むコメント内で Java コードの実行が許可されるのはなぜですか? 質問する

次のコードは、「Hello World!」という出力を生成します (本当に、試してみてください)。

public static void main(String... args) {

   // The comment below is not a typo.
   // \u000d System.out.println("Hello World!");
}

その理由は、Java コンパイラが Unicode 文字を\u000d新しい行として解析し、次のように変換されるためです。

public static void main(String... args) {

   // The comment below is not a typo.
   //
   System.out.println("Hello World!");
}

その結果、コメントが「実行」されることになります。

これは悪意のあるコードや悪意のあるプログラマが思いつくあらゆるものを「隠す」ために使用できるのに、なぜコメントで許可されるのでしょうか?

なぜこれが Java 仕様で許可されているのでしょうか?

アップデート:

元の質問では、IntelliJ Idea を使用しました。そして、@dhke が指摘したように、IntelliJ は間違っていました。しかし、Idea 2024.1.1 では問題が直接解決されていることに気付きました。書式設定により、コメントではないことがわかります。さらに、自動書式設定では、\u000d が実際の新しい行に変更されます。(この問題がいつ解決されたかはわかりません)

IntelliJ IDEA 2024.1.1

ベストアンサー1

Unicode のデコードは、他のあらゆる語彙の翻訳の前に行われます。この主な利点は、ASCII と他のエンコードを簡単に切り替えられることです。コメントの開始位置と終了位置を把握する必要さえありません。

前述の通りJLSセクション3.3これにより、ASCII ベースのツールでソース ファイルを処理できるようになります。

[...] Java プログラミング言語は、Unicode で記述されたプログラムを ASCII に変換する標準的な方法を指定し、プログラムを ASCII ベースのツールで処理できる形式に変換します。 [...]

これにより、Java プラットフォームの重要な目標であったプラットフォーム独立性 (サポートされる文字セットの独立性) が根本的に保証されます。

ファイル内の任意の場所に任意の Unicode 文字を記述できるのは便利な機能であり、非ラテン言語でコードを記述する場合、コメントでは特に重要です。このように微妙な方法でセマンティクスに干渉する可能性があるという事実は、単なる (残念な) 副作用です。

このテーマには多くの落とし穴があり、Java パズルJoshua Bloch と Neal Gafter による次の変種が含まれていました。

これは合法的な Java プログラムですか? もしそうなら、何が印刷されますか?

\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

(このプログラムは単純な「Hello World」プログラムになります。)

このパズルの解答では、次の点を指摘しています。

もっと真面目な話、このパズルは前の 3 つの教訓を強化するものです。Unicodeエスケープは、他の方法では表現できない文字をプログラムに挿入する必要がある場合に不可欠です。それ以外の場合は避けてください。


ソース:Java: コメント内でコードを実行する?!

おすすめ記事