質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

5回答

5546閲覧

StringBuilderとStringの違い

sobue

総合スコア329

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

0クリップ

投稿2016/05/03 09:12

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の文字列の連結結果が違うのが
中の処理がどうなっているかがわかりません。
宜しくお願いします。

raccy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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

yohira0616

総合スコア255

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sobue

2016/05/05 10:05

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

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

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sobue

2016/05/05 10:10

可変オブジェクト・不変オブジェクトという分け方があるのですね。非常に勉強になります。回答ありがとうございます。
guest

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

HiroshiWatanabe

総合スコア2160

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sobue

2016/05/05 10:09

表題に関しては表現があまり上手ではないので少し違うことを書いているかもしれませんが的確に答えていただきありがとうございます。
guest

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

TetsujiMiwa

総合スコア1124

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sobue

2016/05/05 10:14

回答ありがとうございます。皆様とても詳しくベストアンサーは決めづらいのですが、個人的には一番わかりやすく答えていただいたので、ベストアンサーとさせていただきます。
guest

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

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sobue

2016/05/05 10:11

補足、ありがとうございます。参考を入れていただいていますが英語が読めません・・・。 やはり読めるようにならないとこの先厳しいのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問