文字列比較とequalsを理解する
表示が同じでも同じオブジェクトとは限りません。Stringのequalsは文字の並び、==は参照の同一性を調べます。リテラル、new、定数式、nullを組み合わせて比較の意味を確かめます。
この単元で学ぶこと
- equalsと==の比較対象を区別する
- 文字列リテラルと定数式の共有を説明する
- nullやStringBuilderを含む比較を判断する
本文解説
内容と参照の二つの問い String a=new String("cat");String b=new String("cat");では同じ文字を持つ別オブジェクトです。a.equals(b)はtrue、a==bはfalseです。利用者が入力したパスワードや名前の文字列を比べる目的なら、同じ実体を参照するかではなく内容の一致が必要です。==で偶然一致する例だけを見て選びません。
リテラルの共有 String a="cat";String b="cat";では同じ文字列リテラルが共有され、a==bもtrueです。これを文字列プールと呼びます。new String("cat")は別のStringを生成するので、リテラルと==で比較するとfalseです。同じ表示だからtrueなのではなく、参照先を作る規則が違います。
定数式と実行時の連結 "ca"+"t"はコンパイル時に決まる定数式なので"cat"と同じ共有文字列になります。一方、String p="ca";のp+"t"は定数式ではなく、実行時連結の結果をリテラルと==で比較するとfalseです。内容は同じなのでequalsはtrueです。コンパイラの実装によってこの参照比較の結果が自由に変わるわけではありません。
finalと定数変数 final String p="ca";ならpは定数式で初期化された定数変数なので、p+"t"も定数式になります。final String p=new String("ca");はfinalでも定数変数ではありません。finalという単語だけで判断せず、型と初期化式も確認します。intern()を使うと同じ内容を表すプール内の代表参照を得られます。
nullを含む比較 String s=null;でs.equals("x")はNullPointerExceptionですが、"x".equals(s)はfalseです。equalsを呼ぶ受け手が存在するかが違います。java.util.Objects.equals(a,b)は両方nullならtrue、一方だけnullならfalse、それ以外では内容のequalsを使えます。==によるnullチェックと、内容比較を目的で分けます。
大文字小文字と余分な文字 "Java".equals("java")はfalseです。equalsIgnoreCaseならこのASCII例ではtrueになりますが、空白の無視や前後のtrimは行いません。"A ".equalsIgnoreCase("a")はfalseです。また国や言語の照合規則まで自動的に適用する方法ではありません。要件で何を同一とするかを明確にします。
String以外を渡したら String.equals(Object)は相手がStringで、文字列内容が同じ場合にtrueです。"abc".equals(new StringBuilder("abc"))はfalseです。StringBuilderはequalsを内容比較へ変更していないため、別Builder同士のequalsもfalse。内容を比べるならtoString後のequals、またはString.contentEquals(CharSequence)を使います。
順序の比較 compareToは辞書式の順序を表すintを返し、同じなら0です。最初に異なるcharの値の差、片方が完全な接頭辞なら長さの差で結果が決まります。"a".compareTo("c")は-2であり、負なら必ず-1とは限りません。"2"と"10"も数値ではなく文字列として比較されます。Unicodeや言語別の自然な順序とは分けて考えます。
図解
重要ポイント
- ==は同じオブジェクト、String.equalsは同じ文字列内容。
- 定数式と実行時の連結を区別する。
- nullでの呼出しとnullを引数にすることは違う。
- compareToは符号で順序を読み、必ず±1とは考えない。
間違えやすい点
- リテラル比較だけで==を内容比較に使わない。
- finalだけでは定数変数とは限らない。
- StringBuilder.equalsを内容比較に使わない。
用語解説
- 参照同一性
- 二つの参照が同じオブジェクトを指す性質。
- 文字列プール
- 同じ文字列内容の代表オブジェクトを共有する仕組み。
- 定数式
- 規定された構成要素からなり、コンパイル時に値が定まる式。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/StringBuilder.html
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.10.5
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.21.3
確認問題の出題・採点や学習履歴の保存にはログインが必要です。