2012-05-15 14 views
137
String s = "hello"; 
    String backup_of_s = s; 
    s = "bye"; 

この時点で、バックアップ変数には元の値「hello」が含まれています(これはStringの不変性のためですか?)。文字列をJavaでどのようにコピーすればよいですか?

しかし、実際に安全なこのメソッドで文字列をコピーすることはできますか(これはもちろん、通常の変更可能なオブジェクトをコピーすることは安全ではありません)、またはこれを書く方が良いですか? :

String s = "hello"; 
    String backup_of_s = new String(s); 
    s = "bye"; 

つまり、これらの2つのスニペットの違いは何ですか?


EDIT - 最初のスニペットが安全である理由:

は私がちょうどもう少し詳細に物事を説明させて、すでに提供良い回答に基づいて(本質的問題に焦点を当てました2つのスニペット間のパフォーマンスの差異):

文字列はJavaでは不変です。つまり、Stringオブジェクトは構築後に変更できません。したがって 、

String s = "hello";は、新しい文字列インスタンスを作成し、s

String backup_of_s = s;新しい変数backup_of_sを生成し、それが現在のオブジェクトを参照するように初期化する(sインスタンス/オブジェクトへの参照である)にそのアドレスを割り当てますsによって参照される。

注:文字列の不変性は、このオブジェクトが変更されないことが保証されます:私たちのバックアップが安全である

注2:このオブジェクトは、限り、それは少なくとも一つによって参照されるように破壊されないことをJavaのガベージコレクションメカニズム保証(この場合はbackup_of_s)変数

最後に、s = "bye";は、(不変の、それが唯一の方法だから)、別の文字列のインスタンスを作成し、それが今、新しいオブジェクトを参照するようs変数を変更します。

答えて

94

文字列は不変なので、両方のバージョンが安全です。しかし、後者は効率が悪い(余分なオブジェクトを作成し、場合によっては文字データをコピーする)。

これを念頭に置いて、最初のバージョンを優先する必要があります。

+11

不変性はそれとは関係ありません。これは単にオブジェクト参照がどのように機能するかです。同等のStringBuilderの例を提供することができます。 – GriffeyDog

+1

@BalusC、私は新しいString()がJVMのStringプール内に何かを作成することができないのか分かりません。文字列リテラルとintern()経由でプールにコミットされたリテラルのみがプール内にあります。 – Snicolas

+2

@GriffeyDog:質問を文字通り読みにくいです。私が言っていることは、誰かが文字列を変更する恐れなしに、文字列オブジェクトへの参照を与えることは安全であるということです。 – NPE

9

2番目のバージョンでは、余分な文字列オブジェクトを作成する必要がないため、効率的ではありません。

不変性とは、最初のバージョンが期待どおりに動作することを意味し、したがって、優先する方法です。

12

文字列はなので、参照されているオブジェクトは変更できないため、参照をコピーするだけでコピーできます。

だから、何の問題もなく、あなたの最初の例のようにコピーすることができます。

String s = "hello"; 
String backup_of_s = s; 
s = "bye"; 
-10
String str1="this is a string"; 
String str2=str1.clone(); 

どのようにこのようなコピーはどうですか? str1のデータは、str2が参照であり、それ以降の処理で変更された場合、影響を受けないように、新しいコピーを作成する方が良いと思います。

+3

'String'は不変です。ストリングのクローン作成はあまり意味がありません。 – Vladimir

+11

'String.clone()'は存在しません... – glen3b

0

第2のケースでもStringプールが非効率的であるため、リターン参照時にintern()を明示的に呼び出してインターンにする必要があります。

関連する問題