5.2 参照型変数とnull値～Java Basic編

### はじめに

#### 自己紹介

皆さん、こんにちは、Udemy講師の斉藤賢哉です。私はこれまで、25年以上に渡って企業システムの開発に携わってきました。特にアーキテクトとして、ミッションクリティカルなシステムの技術設計や、Javaフレームワーク開発などの豊富な経験を有しています。
様々なセミナーでの登壇や雑誌への技術記事寄稿の実績があり、また以下のような書籍も執筆しています。
* [「マスタリング Java EE 5」（2007年）](https://amzn.asia/d/j0txqK5)
* [「アプリケーションアーキテクチャ設計パターン」（2017年）](https://amzn.asia/d/9avaCyF)

いずれも**Java EE**（**Jakarta EE**）を中心にした企業システム開発のための書籍です。中でも [「アプリケーションアーキテクチャ設計パターン」](https://amzn.asia/d/9avaCyF)は、（Javaに限定されない）比較的普遍的なテーマを扱っており、内容的にはまだまだ陳腐化していないため、興味のある方は是非手に取っていただけると幸いです（中級者向け）。

#### Udemy講座のご紹介

この記事の内容は、私が講師を務めるUdemy講座『**Java Basic編**』の一部の範囲をカバーしたものです。『**Java Basic編**』はこちらの[**リンク**](https://www.udemy.com/course/learn-java-se-basic/?referralCode=594C958456356851C97C)から購入できます（セールス対象外のためいつも同じ価格）。また**定価の約30%OFFで購入可能なクーポン**をQiita内で定期的に発行していますので、興味のある方は、ぜひ私の他の記事をチェックしてみてください。

この講座は、以下のような皆様にお薦めします。
* Javaの言語仕様や文法を正しく理解すると同時に、現場での実践的なスキル習得を目指している方
* 新卒でIT企業に入社、またはIT部門に配属になった、新米システムエンジニアの方
* 長年IT部門で活躍されてきた中堅層の方で、学び直し（リスキル）に挑戦しようとしている方
* 今後、フリーランスエンジニアとしてのキャリアを検討している方
* 「**Chat GPT**」のエンジニアリングへの活用に興味のある方
* 「**Oracle認定Javaプログラマ**」の資格取得を目指している方
* IT企業やIT部門の教育研修部門において、新人研修やリスキルのためのオンライン教材をお探しの方

#### この記事を含むシリーズ全体像

この記事はJava SEの一部の機能・仕様を取り上げたものですが、一連のシリーズになっており、**シリーズ全体でJava SEを網羅**しています。また認定資格である「**Oracle認定Javaプログラマ**」（Silver、Gold）の範囲もカバーしています。シリーズの全体像および「Oracle認定Javaプログラマ」の範囲との対応関係については、以下を参照ください。

https://qiita.com/KenyaSaitoh/items/4711a078a851510bc4da

## 5.2 参照型変数とnull値

### チャプターの概要

このチャプターでは、参照型変数の考え方や、初期値であるnull値について学びます。

### 5.2.1 参照型変数とnull値

#### 参照型変数の特徴

チャプター3.2で触れたように、変数には、プリミティブ型と参照型があり、さらに参照型には、配列型、クラス型、インタフェース型といった種類があります。参照型変数とは、データそのものではなく、実データのメモリ上の配置場所（これをアドレスと呼ぶ）への「参照」を表す変数です。
ここでは配列型を取り上げて、参照型変数の特徴を説明します。まず再び以下のコードを見てください。

```java:snippet_1 (Main_5_2)
int[] scores = {650, 570, 700};
```

ここで変数scoresは配列なので、参照型変数の一種です。すなわち変数scoresには、実データである650、 570、700といった値が直接格納されているわけではなく、実データを参照している形になります。これは以下のようなイメージです。

【図5-2-1】配列と参照型変数
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/b5a375d9-cd63-fed4-5a3b-3cadb2585a99.png)

変数がデータを表しているのか、実データへの「参照」を表しているのかという違いは、通常はあまり意識する必要はありません。ただし変数を別の変数に代入すると、両者の挙動の違いが表れます。以下のコードを見てください。

```java:snippet_2 (Main_5_2)
int[] scores = {650, 570, 700};
int[] scores2 = scores; // 配列から配列に代入する
scores2[0] = 660; // 代入先の値を書き換える
System.out.println(scores[0]); // 代入元はどうなる？
```

このコードのように配列型変数を別の配列に代入すると、配列に格納されている値（要素）が代入されるわけではなく「参照」が代入されるため、同じ実データを指す2つの変数が登場することになります。

【図5-2-2】配列型変数から配列型変数への代入
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/13845ce1-6f2f-c563-2fce-e5443e54aa39.png)

このような状態で代入先である変数scores2の値を更新すると、代入元である変数scoresも同じ実データを参照しているため、値が書き換わります。従ってこのコードを実行すると、660が表示されます。
なお代入元である変数scoresの方を更新しても、同様に代入先である変数scores2の値が書き換わります。

:::note warn
配列型変数やクラス型変数（チャプター7.1参照）、およびインタフェース型変数（チャプター12.1参照）では、変数の代入が行われた場合に、実データが代入されるわけではない、という点には注意が必要です。
:::

#### null値

Javaでは「参照型変数に値が何も格納されていない状態」をnullと言い、その時の「空の値」をnull値と呼びます。
参照型変数の初期値はnull値です。null値は、キーワードnullによって表します。
例えばString型変数strに明示的にnull値を代入する場合は、`String str = null`となります。特にローカル変数の場合、宣言と同時に初期値を代入するのが基本ですが、宣言した後の条件分岐や例外処理の中で初期値が決まる場合には、このように宣言時にnull値を代入しておくケースが一般的です。ただし宣言時にnull値を代入しなくても、コンパイルエラーにはなりません。
さてnull値の取り扱いについて、注意しなければならないことがあります。それは、参照型変数がnull値の場合、その変数が内包する要素（メンバー）にアクセスしようとすると、NullPointerExceptionという例外（Javaにおけるエラー）が発生する、という点です。
従ってnull値の可能性がある変数に対しては、メンバーにアクセスする前に（if文によって）null値かどうかをチェックし、例外の発生を回避しなければなりません。このようなチェックを、nullチェックと呼びます。

:::note warn
null値の可能性がある変数に対しては、内包する要素（メンバー）にアクセスする前にnullチェック行い、例外の発生を回避する必要があります。nullチェックについては、チャプター21.2にて取り上げます。
:::

### このチャプターで学んだこと

このチャプターでは、以下のことを学びました。

1. 参照型には配列型、クラス型、インタフェース型といった種類があり、いずれもデータではなくメモリ上の配置場所への「参照」を表すこと。
1. 参照型変数を代入すると「参照」であるがゆえの特性が顕著に表れること。
1. null値の概念とnullチェックについて。