java
1 2public class AssignmentOperator { 3 4 public static void main (String[] args){ 5 6 StringBuilder sb1 = new StringBuilder("abc"); 7 StringBuilder sb2 = sb1; 8 sb1.append("de"); 9 10 System.out.println("sb1 = " + sb1); 11 System.out.println("sb2 = " + sb2); 12 13 String str1 = "ABC"; 14 String str2 = str1; 15 str1 = str1 + "DE"; 16 17 System.out.println("str1 = " + str1); 18 System.out.println("str2 = " + str2); 19 } 20} 21
上記のコードで
結果
sb1 = abcde
sb2 = abcde
str1 = ABCDE
str2 = ABC
になるのですが、StringとStringBuilderの文字列の連結結果が違うのが
中の処理がどうなっているかがわかりません。
宜しくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答5件
0
まず、javaの代入はint,double,char,booleanなどの基本データ型を除いてすべて「参照を代入」します。
これは、「内容そのもの」をコピーしているのではなく、「内容への行き先」をコピーするということです。
なので、
java
1StringBuilder sb1 = new StringBuilder("abc"); 2StringBuilder sb2 = sb1;
この処理で変数sb2とsb1は、実は「実態は同じもの」を指しています。
java
1new StringBuilder("abc");
した時に、StringBuilderオブジェクトの本体がメモリ上に配置され、sb1はその本体への「行き先」を持ちます。
java
1sb2=sb1
では、sb2はsb1と同じ「行き先」を持つようになります。行き先は同じですが、本体は一つしかありません。
sb2→StringBuilderの本体←sb1
というイメージです。
java
1sb1.append("de");
これは、「sb1が持っている行き先のStringBuilderオブジェクト本体に"de"という文字列を追加せよ」という命令です。
sb2も同じものを指していますから、
sb1 = abcde
sb2 = abcde
となります。
次にStringクラスですが、これも参照代入なので、
java
1String str1 = "ABC"; 2String str2 = str1;
この時点でstr1とstr2は実態は同じものを見ています。
ここで、実はStringクラスは不変オブジェクトなので、オブジェクトの中身を変えることができません。
なので、
java
1str1 + "DE";
これは、「str1の指す文字列に"DE"という文字列を追加した新しい本体を作る」ことを意味しています。
java
1str1 = str1 + "DE";
という代入式では、「str1の指す文字列に"DE"という文字列を追加した新しい本体を作り、その行き先を変数str1に新しく代入する」という処理になります。
この時参照の行き先は
str2 → 最初に作った”ABC” の本体
str1 → 先ほど新しく作成された”ABCDE” の本体
となるので、
str1 = ABCDE
str2 = ABC
となります。
投稿2016/05/03 09:32
総合スコア257
0
StringBuilderは可変オブジェクトです。appendなどのメソッドはオブジェクトが持つ情報を書き換えます。
一方、Stringは不変オブジェクトです。+演算子で文字の付け足しをしたり、メソッドで部分文字列を生成したりなどするときは、新たなStringオブジェクトを生成します。
また先の回答者様の通り、Javaにおいてプリミティブ型(int,long,doubleなどの数値型,文字型char,論理型boolean)を除き、すべて参照型です。代入の操作は、そのオブジェクトが存在する場所を入れています。その変数が見ているオブジェクトと考えればいいでしょう。
上記例では、最初の代入の段階ではStringBuilderの場合もStringの場合も、2つの変数が同じオブジェクトを見ている状態です。
StringBuilderの場合、変数sb1が見ているオブジェクトに対して「"de"を追加する」という操作をしています。ところが、このオブジェクトはsb2も見ているので、どちらの変数から出力してみても同じ結果が出てきます。
一方、Stringの場合、
java
1str1 + "DE"
これはstr1が見ているStringに"DE"を追加した新しいStringを生成することを意味しています。元の"ABC"というStringには変化はありません。
そしてこれをstr1に代入するということは、str1が見る先がこの新しいStringに変わるということです。str2が"ABC"を見ていることに変化はないので、str1が"ABCDE",str2が"ABC"という結果になったのです。
投稿2016/05/03 10:30
総合スコア20675
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
StringとStringBuilderの違いという話しではなさそうな…?
StringBuilder sb1 = new StringBuilder("abc");
StringBuilder sb2 = sb1; ← sb2 と sb1 は「同じデータを指している状態」です(実体が1つで共有してる状態)
sb1.append("de"); ← sb1 の中身が変わったので同じ場所を指している sb2 も同じ結果になります
String str1 = "ABC"; ← str1 は "ABC" を指している()
String str2 = str1; ← str2 と str1 は「同じデータを指している状態」でここまでは上と同じです
str1 = str1 + "DE"; ← str1 が指している場所は ()の"ABC"ではなく "ABCDE" という新しい別の場所を指すようになった
例えば
String str3 = str1 + "DE";
としたら分かり易いでしょうか?
この場合 str1 が指す場所は変化していませんよね?
またstr1が指す先の中身が直接編集(加工)されている訳でもありませんよね?
つまり「str1 = 」とstr1を新しい値で初期化しているので(*)の時に行ったstr1とは別の場所を指すように変化しているという事です。
ざっくりまとめると
・前者のケースでは2つは同じ場所を参照していて参照先の中身を直接(appendで)加工している
・後者のケースでは2つは途中まで同じ場所を参照していたが"DE"を追加した結果を参照するようにstr1の参照先を変更した時点でstr1とstr2の参照先が別物になった
という違いです。
投稿2016/05/03 10:09
総合スコア2160
0
ベストアンサー
まず、new StringBuilder("abc");で、メモリのどっかにオブジェクトが割り当てられる。
それを、StringBuilder sb1 = とすることで、sb1にオブジェクトの居場所握らせることができる。
それで、次のStringBuilder sb2 = sb1;ってのは、sb2にsb1が握っている居場所を伝えている。
だから、sb1とsb2は、new StringBuilder("abc");の同じ居場所を握っていることになる。
なので、
System.out.println("sb1 = " + sb1);
System.out.println("sb2 = " + sb2);
は同じ結果になる。
さて、次に String str1 = "ABC";も、同様に、メモリのどっかにオブジェクトが割り当てられて、
str1にオブジェクトの居場所を握らせて、
String str2 = str1;で、str2にstr1が握っている居場所を伝えているわけだけど、
次のstr1 = str1 + "DE";と言うのは、str1のオブジェクトと"DE"というオブジェクトを連結させた新しいオブジェクトをメモリに割り当てて、その居場所をstr1に伝えている。
つまりこの時点で、str1とstr2の指し示すオブジェクトは別物になっている。
だから
System.out.println("str1 = " + str1);
System.out.println("str2 = " + str2);
は違う結果となるわけです。
投稿2016/05/05 02:05
総合スコア1124
0
皆様の素晴らしい回答の通りなので、私から一点だけ補足させていただきます。
Java
1str1 = str1 + "DE";
は
Java
1str1 = (new StringBuilder()).append(str1).append("DE").toString();
と解釈されます。※ 古いバージョンのJavaではStringBuilderの代わりにStringBufferが使われます。
他の皆様がおっしゃるとおり、str1 + "DE"
では新しいStringが作成されます。どういう風に作成されるかというと、上のコードのようになっていると言うことです。Stringに対する+
演算子はメソッドや関数ではありません(C++やRubyとは大きく異なる点です)。ましてや、intなどの数字型とも異なる処理をします。StringBuffer(昔のJava)やStringBuilder(最近のJava)等を使って、文字列(数字の場合は文字列にした後)を連結し、新しい文字列を作るという動作をします。なお、連続して書いている場合は、一つのStringBuffer(またはStringBuilder)を使ってなるべく効率よく作るようになっています。新しいStringを作成されるとは何なのか?という答えが、このStringに対する+
演算子の仕様と言うことです。
参考: Java 8 Language Specification | 15.18.1. String Concatenation Operator +
投稿2016/05/03 12:27
総合スコア21751
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/05/05 10:05