Stringの不変性

このレッスンでできるようになることは、String が不変であることを踏まえ、戻り値を捨てているコードを一目で見抜けるようになることです。

まず予測してみます

次のコードは何を出力するでしょうか。

String s = " Java "; s.trim(); s.toUpperCase(); System.out.println(s);

出力は Java を大文字にしたものではなく、前後の空白が付いたままの Java です。何も変わりません。

String は不変

String は不変です。いったん作った文字の並びは、あとから書き換えられません。trimtoUpperCasereplacesubstringconcat も、元の文字列には一切手を触れず、加工結果を新しい 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 自体が不変だからです。

演習

入力を整えるはずのメソッドが、何も整えずに返してきます。不変性を思い出して直してください。

要件

  1. 前後の空白を取り除き、内側の半角スペースをすべて削り、大文字にすること
  2. 戻り値は 整形後の文字列 と 元の文字列の長さ を半角コロンでつないだものにすること
  3. 元の raw は加工しないこと

入出力例

clean(" ab cd ")"ABCD:7" clean(" java silver ")"JAVASILVER:15" clean("x")"X:1" clean(" Silver ")"SILVER:8"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.java
学習モード

メモ

Stringの不変性

⌘S で保存