Stringの不変性
このレッスンでできるようになることは、String が不変であることを踏まえ、戻り値を捨てているコードを一目で見抜けるようになることです。
まず予測してみます
次のコードは何を出力するでしょうか。
String s = " Java ";
s.trim();
s.toUpperCase();
System.out.println(s);出力は Java を大文字にしたものではなく、前後の空白が付いたままの Java です。何も変わりません。
String は不変
String は不変です。いったん作った文字の並びは、あとから書き換えられません。trim も toUpperCase も replace も substring も concat も、元の文字列には一切手を触れず、加工結果を新しい String として返すだけです。
ですから戻り値を受け取らずに呼ぶと、作られた新しい文字列はどこにも保持されずに捨てられます。呼び出した行は、実質何もしていないのと同じです。
s = s.trim(); // これで初めて s が変わりますコンパイルは通りますし、警告も出ません。だから試験で狙われます。「メソッドを呼んだのに結果が変わらない」という形の問題を見たら、まず代入があるかを確認してください。
連結も同じ
+ による連結も、そのつど新しい String を作ります。ループの中で += を繰り返すと、回数ぶんインスタンスが生まれて重くなります。何度も書き換えたいときは、可変の StringBuilder を使います。
StringBuilder sb = new StringBuilder("a");
sb.append("b"); // これは sb 自身が変わりますStringBuilder の append は自分自身を書き換えたうえで自分を返すので、戻り値を捨てても結果が残ります。String と StringBuilder で挙動が逆になる点が、そのまま出題の材料になります。
メソッド引数に渡しても変わらない
static void edit(String t) {
t = t + "!";
}この呼び出しでも、呼び出し側の文字列は変わりません。渡されるのは参照の複製であり、しかも String 自体が不変だからです。
演習
入力を整えるはずのメソッドが、何も整えずに返してきます。不変性を思い出して直してください。
要件
- 前後の空白を取り除き、内側の半角スペースをすべて削り、大文字にすること
- 戻り値は 整形後の文字列 と 元の文字列の長さ を半角コロンでつないだものにすること
- 元の raw は加工しないこと
入出力例
clean(" ab cd ") → "ABCD:7"
clean(" java silver ") → "JAVASILVER:15"
clean("x") → "X:1"
clean(" Silver ") → "SILVER:8"