参照型とnullを理解する

参照型の変数はオブジェクトそのものを変数へ詰め込むのではなく、オブジェクトを参照する値を持ちます。参照のコピー、内容の変更、nullへの再代入を分けると、共有と例外の原因が見えます。

この単元で学ぶこと

  • 参照変数とオブジェクトを区別する
  • 参照コピーと別オブジェクト生成を追跡する
  • null検査・参照解除・内容比較を区別する

本文解説

参照する変数 String s="cat";ではsは文字列オブジェクトを参照します。int[] a=new int[2];ではaは配列を参照します。クラス型、インタフェース型、配列型が参照型に含まれます。実際のオブジェクトと、その参照を入れる変数を別々に考えます。

nullは空ではない String s=null;は文字列を参照していません。String s="";なら長さ0の文字列を参照しています。前者にs.length()を呼ぶと例外、後者なら0です。空欄という値と、値が存在しないという状態の違いを表せます。

nullを検査する s==nullは参照値を比べるので、sがnullでも例外になりません。s!=null&&s.length()>0ならnullでないときだけ長さを調べます。先にs.length()を呼んでからnullを確認しても、先の例外は防げません。

代入で参照をコピー int[] a={2};int[] b=a;では配列は一つです。b[0]=9;の後はa[0]も9です。変数bの中へ配列要素全体をコピーしたのではなく、同じ配列へ到達できる参照値をコピーしたためです。

newで別の実体を作る int[] a={2};int[] b={2};では同じ内容の配列が二つできます。a==bはfalseで、b[0]=9;にしてもa[0]は2です。内容の一致と同じ実体であることを区別します。配列の==は要素を一つずつ比較しません。

参照の再代入 int[] a={2};int[] b=a;b=null;としてもa[0]は2です。変更したのはbが持つ参照だけで、aや配列を消していません。逆にa=null;の後でもbが元の配列を参照していればbから利用できます。

Stringの内容比較 String a=new String("hi");String b=new String("hi");ならa==bはfalse、a.equals(b)はtrueです。newで別のStringを作っていますが内容は同じだからです。文字列リテラルの共有があるため==でたまたま一致する場合を、一般的な内容比較と考えないようにします。

宣言型から利用できる操作を決める Object x="cat";はStringをObject型で参照します。x.toString()はObjectにもあるので呼べますが、x.length()はObjectにないためコンパイルエラーです。実体がStringだからといって、宣言型にないメソッドをそのまま呼べるわけではありません。

図解

参照のコピーと内容の共有
変数を書き換えるのか、参照先を書き換えるのかを区別する。

重要ポイント

  • 配列とStringも参照型。
  • nullはどのオブジェクトも参照しない値。
  • 参照の代入はオブジェクトの複製ではない。
  • ==は参照の一致、String.equalsは内容を比べる。

間違えやすい点

  • 一つの変数をnullにしても他の変数までnullにはならない。
  • 空のStringとnullは違う。
  • 参照型のローカル変数も読む前に初期化が必要。

用語解説

参照
オブジェクトを指し示す値。Javaでは数値アドレスを直接操作しない。
null
オブジェクトを参照しない特別な値。
参照解除
参照先のフィールド・配列要素・インスタンスメソッド等へアクセスすること。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。