この回では、文字列の比較、配列の範囲、参照の共有を扱います。前提は第03回です。
同じ内容と同じ物は違う
プリミティブ型のintなどは値そのものを比較できます。Stringのような参照型で == を使うと、同じオブジェクトへの参照かを比較します。文字の並びを比較したければequalsを使います。たまたま同じ結果になった実験だけで判断しないことが大切です。
import java.util.Arrays;
import java.util.Objects;
public class Main {
public static void main(String[] args) {
String a = new String("Java");
String b = new String("Java");
System.out.println(a == b);
System.out.println(a.equals(b));
int[] original = {10, 20};
int[] shared = original;
int[] copied = Arrays.copyOf(original, original.length);
shared[0] = 99;
System.out.println(original[0] + "," + copied[0]);
String missing = null;
System.out.println(Objects.equals(missing, "Java"));
String text = "A😀";
System.out.println(text.length());
System.out.println(text.codePointCount(0, text.length()));
}
}
Main.javaでの出力はfalse、true、99と10、false、3、2です。配列を代入しただけでは要素は複製されません。コピーした配列なら今回のint要素は独立します。ただし、オブジェクトの配列をコピーすると要素の参照は共有されるため、深い複製とは限りません。
文字数は一種類ではない
Stringは変更不能です。加工した文字列は新しい結果として返り、元の文字列は書き換わりません。大量の連結を繰り返す場面ではStringBuilderも候補になります。
lengthはUTF-16コード単位の数です。絵文字などは二つの単位を使う場合があります。コードポイント数でさえ、人が見た文字数と常に一致するわけではありません。結合文字や複数の絵文字をまとめた表示があるためです。「最大20文字」という仕様では、どの数え方かを決めます。
配列の有効な添字は0からlength未満です。i <= array.length は末尾を一つ越えます。nullは「参照先がない」状態で、空文字列や空配列とは別です。nullに対してメソッドを呼べばNullPointerExceptionになります。
練習と解答
練習:文字列配列の先頭だけを大文字に変えるメソッドを作り、呼び出し元にも変更が見える理由を説明してください。
解答の要点:values[0] = values[0].toUpperCase(java.util.Locale.ROOT); は新しい文字列への参照を、共有配列の先頭へ代入します。String自体を変更しているのではありません。空配列とnullを許すかは契約で決め、必要なら先に検査します。
公式資料
String APIと配列が参照先です。
Java全20回の目次 | 前の回 | 次の回