【Java初心者】参照型とNull

データ型の一種である参照型の仕組みと参照型で利用されるNullについて解説していきます!今回は配列をメインに用いて参照型について説明していきます。

参照型とは

プログラミングで取り扱うデータ型は、基本型と参照型の2種類に大きく分けることができます。基本型はデータの取り扱いがイメージしやすいのですが、参照型は初心者がつまずきやすい項目の一つです。

基本型のint型変数と参照型のint[]配列を比較しながら参照型について説明していきます。

基本型と参照型の違い

int number = 1;
int[] numbers = {1,2};

このコードは初期値の代入を表していますが基本型も参照型も、ソースコード上での見た目はそこまで違いがありません。最も決定的な基本型と参照型の違いは中に保存するデータにです。

  • 基本型は、代入したデータの値がそのまま変数の箱に入ります
  • 参照型は、代入したデータの存在する場所の住所が箱に入ります

例えば宝探しでイメージすると、宝物を探して箱を開いた場合、基本型は箱の中にお宝が入っていますが、参照型は宝物のありかを示した地図が箱の中に入っているイメージです。

上記のように、基本型は変数として用意されたメモリ上の住所の中に値が直接入れられます。

参照型は、宣言された箱とは別に値が入っている領域が確保されます。そして、参照型変数の箱の中には値が入っているメモリ上の住所が格納されます。配列などいくつかの要素が連なっているデータでは先頭の要素の住所が変数に代入されます

配列における参照値の考え方

配列では、配列の先頭要素の住所が変数の中に代入されます。そして、プログラムはその先頭の住所を基準にして配列の後ろの要素を取得しています。

int[] numbers = new int[3];

上記のように配列の変数宣言がされた時に実際のメモリ上では、3つの動作が行われています。

  • メモリ上にint[]型の配列変数numbersが作成される。
  • メモリ上にint型の要素を3つ持つ配列が作成される。
  • numbersに配列の先頭要素である[0]の住所が代入される
int[] numbers = new int[3];
numbers[0] = 1;
numbers[1] = 2;

上のコードのように、特定の要素に対して値を代入したり要素を使用した処理を行う場合には、メモリ上ではまずnumbers[0]の住所を確認しnumbers[1]であれば[0]の次の住所をみる!といった動きをしています。

複数の変数から参照

参照型のデータの仕組みはここまででなんとなく理解できていると思いますが、参照型にはもう一つややこしい使用方法があります。それが複数の参照型変数からの参照です。

基本型
int a = 10;
int b = a;
b = 100;
System.out.print(a);               出力結果:10
System.out.print(b);               出力結果:100

参照型
int[] arrayA = {10,20};
int[] arrayB = arrayA;
arrayB[0] =  100;
System.out.print(arrayA[0]);               出力結果:100
System.out.print(arrayB[0]);               出力結果:100

上のコードでは、基本型と参照型でAの値をBに代入していますが、参照型の変数のarrayAの出力結果が想像していた結果と違うのではないでしょうか?この仕組みについてご説明します。

まず基本型の変数における代入b=aは、aに入っているデータをコピーしてbに代入しているイメージです。aとbにはそれぞれ10という値が入っています。そのため、bの値を上書きしてもaにはなんの影響もありません。

参照型の変数には[参照先の住所]が入っているため、arrayB=arrayAで代入される値は[参照先の住所]です。つまり、実際に参照される値は一つのままで値を参照する変数が増えただけで、2つの変数は同じ値を見ているのです。同じ値を見ているため、arrayBに代入した値がarrayAにも反映されています。

Nullとは

Nullの役割

nullとは、参照型の変数に代入できる初期値のようなものです。参照型の変数に代入できる値は、nullと参照値(値のメモリ上の住所)のみです。

int[] arrayA = null;       ⇦まだ要素数の決まっていない配列の初期値として利用
int[] arrayB = {10,20};
arrayB = null;                 ⇦arrayBを初期化し、配列{10,20}を参照しなくなる

nullは[何もない]ということを表し、参照型の変数に対して代入を行うことでその変数は何も参照しなくなります。少し異なりますが、数値型の変数に0を代入して初期化するようなイメージです。参照型変数を初期化する際には頻繁に利用します。

Nullで起こる例外

参照型使用時にはたびたび[NullPointerException]という例外がプログラム実行時に起きます。Nullが入っているのでデータがおかしいですという意味を表します。これは、Nullが代入されている変数を使用したり、Nullの入っている配列変数の要素に値を代入しようとした時に発生する例外です。

int[] a = {10,20,30};
a = null;                        ⇦配列への参照は切れてしまう。
❌a[0] = 100;                 ⇦aにはnullが入っているためNullPointerException

上記のようにaにはnullが入っており、配列の住所を示していないためにNullPointerExceptionが発生してしまいます。この例外が発生したら、エラーメッセージを読むことは大前提ですが、まず参照型変数に正しく値が入っているか確認を行いましょう!

以上、参考になった方もならなかった方もご覧いただきありがとうございました!