TL; DR:はそれをしないでください。そのコードは、(ab)リフレクションを使用して仕様に違反しています。 JLSによると、String
values cannot change。そのコードは、文書化されていない私的な内部構造にアクセスすることによって文字列の値を変更します。悪いアイデア。何が起こっている
:実行時に、それらはすべてメモリ内の同じ文字列オブジェクトを参照するようにクラスの
等価文字列リテラルは、すべての結合され;クラスの「定数プール」に書き込まれます。したがって、そのクラスの"IMMUTABLE"
のすべての出現は、実際には同じインスタンスString
を参照します。これは、クラスがロードされるとリテラルと変数が同じオブジェクトを参照するので効果で、最後の行
System.out.println("IMMUTABLE");
ことを... ...
System.out.println(someString);
と同等であることを意味しています。
コード(ab)はリフレクションを使用して文字列オブジェクトの非公開の非公開値を上書きするため、オブジェクトが使用されているすべての場所でその更新された状態が見えます。あなたが別のクラスにあなたのSystem.out.println("IMMUTABLE");
ラインを移動し、あなたのコードはsomeString
を修正前にそのクラスがロードされることを保証した場合にも起こる
。これは、クラスがロードされると、定数プール内の文字列がinternedになるため、異なるクラスの同等の文字列定数が同じString
オブジェクトを参照するようになります。これはあなたが頼りにしたいことではありません。ストリングは(最近)インターンプールから逃げ出すことができるからですが、単純なケースではおそらくそれを観察するでしょう。例えばので
、あなたはこの別のクラスだったとします
public class Separate {
public static void show() {
System.out.println("IMMUTABLE");
}
}
をそして、あなたはそれを使用するようにコードを変更し、だけ後someString
を変更:
public static void main(String[] args) throws SecurityException, NoSuchFieldException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException {
String someString = "IMMUTABLE";
// ...
System.out.println(someString); // prints NOTREALLY
Separate.show();
}
あなたが取得したいです
NOTREALLY
IMMUTABLE
...によってSeparate
がロードされている場合は、インテルプールにある文字列のバージョンを既に変更しているので、Separate
をロードすると一致しないため、別のString
オブジェクトを参照してしまいます。
しかし、あなたはSeparate
は、あなたがそれを変更前にロードされていることを確認した場合:
public static void main(String[] args) throws SecurityException, NoSuchFieldException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException {
Separate.show(); // <================ Note
String someString = "IMMUTABLE";
// ...
System.out.println(someString); // prints NOTREALLY
Separate.show();
}
あなたが楽しいのこのビットを取得:
IMMUTABLE
NOTREALLY
NOTREALLY
...Separate
がロードされている時点で、その"IMMUTABLE"
はインタープールのものと同等なので、Separate
はmain
のコードが変更されるString
インスタンス —を使用します。
あなたは不変性を壊すために反省を払っています - あなたはどんな結果を期待していますか? 'setAccessible(true)'を使うと、アクセスできないプライベートフィールドにアクセス可能になります。配列内の値を変更することで、文字列を変更することができます。 –