2016-07-09 5 views
1

JavaのString変数は変更できないため、変更することはできません。"+ ="を使ってJavaで文字列を "変更"するとどうなりますか?

String myString = "Hello."; 
myString += " "; 
myString += "My name is Kevin"; 

我々はこのString()に何かを「追加」するたびに、私たちは、効果的に新しいString()を作成しているが、これはそれがで連結されている文字列と同じ名前を持ちます。これは、変数 "myString"を持つメモリ内に複数の参照があることを意味しますか?

+0

あなたが参照し、実際のオブジェクトへの参照元の違いを誤解されています。連結すると、参照は新しく作成された文字列オブジェクトを指し示します。 –

+1

_name_と呼ばれるものは、実際に_variable_と呼ばれています。オブジェクトと参照には名前はありません。変数は異なる時間に異なるオブジェクトを参照することができ、異なる変数は同じオブジェクトを参照することができます。これは_aliasing_と呼ばれます。 – Seelenvirtuose

答えて

6

あなたは+=Stringを連結/「修正」するたびに、新しいStringオブジェクトを作成し、新しく作成されたStringmyStringという名前の参照を交換しています。そうではありませんが、メモリ内に参照が1つしかありませんが、参照ポイントが変更するたびに変化するオブジェクトがあります。文字列はは不変なので、オブジェクトは「インプレース」で変更できません。

文字列はJavaの不変クラスです。不変クラスは、インスタンスを変更できないクラスです。インスタンス内のすべての情報は、インスタンスの作成時に初期化され、情報は変更できません。不変クラスの多くの利点があります。

String sがJavaで不変であり、これがどのように機能するかを正確に関する詳細なぜを説明great answer on the Programmer's StackExchangeがあります。

String myStringBuilder = new StringBuilder("Hello."); 
myStringBuilder.append(" "); 
myStringBuilder.append("My name is Kevin"); 

System.out.println(myStringBuilder.toString()); 

しかし、String連結は、現代のJavaコンパイラによって自動的にStringBuilder操作に翻訳されています

これを行うための最善の方法は、単にStringBuilder()クラスを使用することです。

+0

メモリ内に参照が1つしかない場合、なぜこの形式の 'String'の変更は、代わりに' StringBuilder() 'を使用すると非効率的であると考えられますか?確かに1つの参照のみがある場合、 '+ ='を使用して 'String 'を変更すると、メモリ使用量は変更されません。 – Shaney96

+0

'+ ='を使うと、新しい 'String()'オブジェクトが毎回作成されなければならないので、 'StringBuilder()'は変更可能であり、インプレースで変更することができます。 – Will

+0

ご回答ありがとうございます。 – Shaney96

2

いいえ、以前の参照にアクセスすることはできません。ガベージコレクタがそれを収集するために残っています。つまり、あなたが文字列変数多くのことをするつもりな変化をrの場合、あなたはStringBuilderのクラスを使用する必要があること、変数の現在の値を保持するメモリで唯一つの基準(「私の名前はケビンです)

ノートがあります。

は、ここであなたは、インターネット

https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html

にこのクラスを使用するための多くの例を見つけることができます StringBuilderクラスのドキュメントへのリンクもここであなたの質問

の詳細な答えがあるさ

When will a string be garbage collected in java

+0

その前のバージョンの 'myString'変数はメモリにまだ残っていますが、もはや参照されていないので" garbage collector "のままになりますか? – Shaney96

+0

はい、あなたは私が答えに追加されたリンクで見ることができるように、文字列で収集するガベージのルールは他と同じです。 –

2
String myString = "Hello."; 

上記は、新しいObjectを作成し、myStringObjectへの参照でメモリに"Hello."を置きます。ここで

myString += " "; 

" "文字列を作成し、メモリに入れ、連結はmyStringによって参照される新しいStringを作成するためになりますされmyString = myString + " ";として、あなたは見ることができます。

"+"の文字列連結はO(N2)の複雑さを持ち、StringBuilderの複雑さはO(N)です。たびたび連結結果のために新しいStringが作成されているのに対して、StringBuilderには一連の文字が含まれています。したがって、String連結は、特に大量のStringを構築する必要がある場合には、StringBuilderを使用するよりも効率が悪いです。

2

Javaは文字列プールを使用します。これは、string interningという概念の実装です。

コンピュータサイエンスでは、文字列インターンは、それぞれ異なる文字列値のコピーを1つだけ保存する方法であり、変更不可能でなければなりません。インターン文字列は、文字列の作成や保留に時間を要するという代償を払って、文字列処理タスクをより時間的または空間的に効率的に処理します。別個の値は、文字列プールに格納されます。

これは、すべての文字列に対して、その特定の文字列のコピーが文字列プールに追加されることを意味します。その正確な文字列を保持するすべての変数は、その文字列プール内のそのコピーを指します。彼らはプログラム内のリテラルをしているので、


文字列Hello.、およびMy name is Kevinは、文字列プールに追加されます。

String myString = "Hello."; 

文字列プール内に既にある文字列Hello.、を指す変数myString開始。

myString += " "; 

文字列Hello.は(末尾に余分なスペースに注意)プールに追加されます。変数myStringはこれをポイントします。

myString += "My name is Kevin"; 

文字列Hello. My name is Kevinがプールに追加されます。変数myStringはこれをポイントします。
変数によって参照されなくなったプール内の文字列are eligible for garbage collectionHello.(末尾にスペースを含む)はガベージコレクションできるようになりました。

+0

"消去されるかもしれません"ということは、古いバージョンのmyStringで使用されているが、コンパイル時に消去されるメモリ内のアドレスがあると言っていますか? – Shaney96

1

ここでは、Stringという参照変数myStringを定義するコードです。

文字列は、それが作成されたら、オブジェクトで行うことができます何も変更がないことを意味し、不変クラスです。

ここで"Hello"は、Stringオブジェクトを作成し、そのオブジェクトをmyStringで参照します。 myString+=" ";が、それはそれでconcaticateで「こんにちは」文字列の別の新しいオブジェクトを作成し、実行取得

String myString = "Hello."; //create a Object String contain Hello and refer to myString 
myString += " "; 
myString += "My name is Kevin"; 

"Hello "新しいオブジェクトが作成され、myStringがそれを参照します。 "Hello"はガベージコレクションの対象です。

もう一度myString += "My name is Kevin";を実行すると、concatenate "Hello "によって別の新しいオブジェクトが作成されます。 新しいオブジェクト"Hello My Name is Kevin"は、文字列型のmyString参照変数によって参照されます。

今、あなたの両方の以前のオブジェクト"Hello""Hello/s"それはガベージコレクションの対象である、その他の参照変数によって参照され、そうではありません。

おかげ

+0

乾杯、ガベージコレクションプロセスは今完全に意味をなす。 – Shaney96

関連する問題