1. ホーム

[解決済み】Javaにおける文字列の不変性

2022-04-06 22:32:07

質問

次のような例を考えてみましょう。

String str = new String();

str  = "Hello";
System.out.println(str);  //Prints Hello

str = "Help!";
System.out.println(str);  //Prints Help!

さて、Javaでは、Stringオブジェクトはイミュータブル(不変)です。では、どうして str には "Help!"という値を割り当てることができます。これは、Javaの文字列の不変性と矛盾していませんか?どなたか、不変性の正確な概念について説明していただけませんか?

編集する

OK。今、私はそれを得ているが、ちょうど1つのフォローアップの質問。次のコードはどうでしょう。

String str = "Mississippi"; 
System.out.println(str); // prints Mississippi 

str = str.replace("i", "!"); 
System.out.println(str); // prints M!ss!ss!pp! 

これは、2つのオブジェクトが再び作成され("Mississippi"と"M!ss!ss!pp!")、参照先の str の後に別のオブジェクトを指しています。 replace() メソッドを使用しますか?

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

str はオブジェクトではなく、オブジェクトへの参照です。 "Hello""Help!" は、2つの異なる String オブジェクトを作成します。このように str を指しています。 という文字列があります。を変更することができます。 を指す しかし、それが 指す .

たとえば、こんなコード。

String s1 = "Hello";
String s2 = s1;
// s1 and s2 now point at the same string - "Hello"

では、何もない 1 に対して、私たちができることは s1 の値に影響を与えるような s2 . これらは同じオブジェクト、つまり文字列 "Hello" - しかし、このオブジェクトは不変であり、変更することはできません。

こんなことをしたら

s1 = "Help!";
System.out.println(s2); // still prints "Hello"

ここでは、オブジェクトの変異と、参照の変更の違いを見てみましょう。 s2 は、最初に設定したのと同じオブジェクトを指しています。 s1 を指すようにします。設定する s1 から "Help!" を変更するだけです。 参照 一方 String オブジェクトは変更されません。

文字列 mutableであれば、このようなことが可能です。

String s1 = "Hello";
String s2 = s1;
s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string
System.out.println(s2); // Prints "Hallo"


OPの編集に対応するために編集しました。

を見ると String.replace(char,char) のソースコード (JDKのインストールディレクトリのsrc.zipにもあります。何かが本当にどう動くのか疑問に思ったら、いつでもそこを見るのがプロのコツです。) このコードがやっていることは、以下の通りです。

  • が1つ以上出現している場合 oldChar が出現する現在の文字列のコピーを作成します。 oldChar に置き換えます。 newChar .
  • もし oldChar が存在しない場合、現在の文字列を返します。

そうそう。 "Mississippi".replace('i', '!') は、新しい String オブジェクトを作成します。この場合も、次のようになります。

String s1 = "Mississippi";
String s2 = s1;
s1 = s1.replace('i', '!');
System.out.println(s1); // Prints "M!ss!ss!pp!"
System.out.println(s2); // Prints "Mississippi"
System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects

を変更した場合、上記のコードがどうなるかを確認することが当面の宿題となります。 s1 = s1.replace('i', '!');s1 = s1.replace('Q', '!'); :)


1 実はこれ 文字列(および他の不変のオブジェクト)を変異させることができます。これはリフレクションを必要とし、とてもとても危険なので、実際にプログラムを破壊することに興味があるのでなければ、決して使ってはいけません。