StringBuilder
このレッスンを終えると、StringBuilder の insert と delete と reverse がどこを書き換えるのかを追えるようになります。
まず予測してください
次の2つは、最後に何が表示されるでしょうか。
String a = "abc";
a.concat("d");
System.out.println(a);
StringBuilder b = new StringBuilder("abc");
b.append("d");
System.out.println(b);答えは abc と abcd です。ここが String と StringBuilder のいちばん大きな違いです。
String は作り直し、StringBuilder は書き換え
String は不変なので、concat も replace も toUpperCase も、新しい String を作って返すだけです。元の変数は 1 文字も変わりません。戻り値を受け取り忘れたコードを見せて「出力は」と聞くのが定番の出題です。
対して StringBuilder のメソッドは、自分自身の中身を書き換えます。そのうえで自分自身を返すので、sb.append("a").append("b") のようにつなげて書けます。返ってきたものは新しいオブジェクトではなく、同じ StringBuilder です。
insert と delete の引数
insert(index, 値) は、index 番目の手前に割り込ませます。insert(0, ">") なら先頭に付きます。長さと同じ値を渡すと末尾に付き、それより大きいと StringIndexOutOfBoundsException になります。
delete(start, end) は start 番目から end 番目の手前までを消します。substring と同じで end は含みません。消える文字数は end - start です。1文字だけ消す deleteCharAt(index) と混同させる問題も出ます。
reverse は破壊的
reverse も新しい文字列を返すのではなく、自分自身をひっくり返します。sb.reverse() を呼んだあとに sb を使うと、もう並びが逆になっています。「reverse の戻り値だけを別の変数に入れて、元の変数も使う」というコードは、両方とも同じ逆順の中身を指すことになります。ここは同一オブジェクトかどうかを問う形でよく狙われます。
長さは length() で取れます。String と違って length はメソッドです。配列の length がフィールドであることと合わせて整理しておいてください。
要件
- base から StringBuilder を作る
- 末尾に感嘆符を append し、続けて先頭に大なり記号を insert する
- そのあと delete(1, 3) を呼ぶ
- この時点の中身を控えてから reverse を呼ぶ
- 控えた中身、reverse 後の中身、reverse 後の長さをこの順にスラッシュでつないで返す
入出力例
build("abcde") → ">cde!/!edc>/5"
build("xyz") → ">z!/!z>/3"
build("hello") → ">llo!/!oll>/5"