1. ホーム
  2. java

[解決済み] このJavaコードスニペットはどのように動作するのですか?(文字列プールとリフレクション) [重複].

2023-05-13 17:18:50

質問

Java文字列プールとリフレクションの組み合わせは、Javaで想像もつかないような結果を生み出すことがあります。

import java.lang.reflect.Field;

class MessingWithString {
    public static void main (String[] args) {
        String str = "Mario";
        toLuigi(str);
        System.out.println(str + " " + "Mario");
    }

    public static void toLuigi(String original) {
        try {
            Field stringValue = String.class.getDeclaredField("value");
            stringValue.setAccessible(true);
            stringValue.set(original, "Luigi".toCharArray());
        } catch (Exception ex) {
            // Ignore exceptions
        }
    }
}

上記のコードが表示されます。

"Luigi Luigi" 

マリオはどうなった?

どのように解決するのですか?

<ブロッククオート

マリオはどうなったのですか?

あなたはそれを変更しました、基本的に。そうです、リフレクションを使えば文字列の不変性を破ることができます...そして文字列インターニングにより、(コンパイル時に解決されたであろうより大きな文字列定数式以外での)マリオの使用はプログラムの残りの部分でquot;ルイジとして終わってしまうことを意味します。

このようなことが、リフレクションがセキュリティパーミッションを必要とする理由です...

式に注意してください。 str + " " + "Mario" ではなく の左結合性により、コンパイル時の連結は一切行われません。 + . これは事実上 (str + " ") + "Mario" であり、そのため、まだ Luigi Luigi . というコードに変更すると

System.out.println(str + (" " + "Mario"));

... すると、次のようになります。 Luigi Mario と表示され、コンパイラは " Mario" を別の文字列に変換して "Mario" .