目次
nullとは?
nullは、変数の値に何も定義されていない(何も入っていない)状態を表す特殊は値です。
Javaのデータ型は大きく「プリミティブ型」と「参照型」の2つに分類されます。
整数を表すint型、文字1つを格納するchar型など、値を直接入れるものはプリミティブ型となり、String型やファイルを読み込むFileInputStreamなどのクラスは参照型になります。
そしてnullを格納できるのは、参照型の変数だけでプリミティブ型の変数にはnullを入れることはできません。
nullを変数に設定
nullを変数に設定するサンプルコードをみてみましょう。nullはダブルクォーテーションなども不要で、そのままnullと記述します。
public class Main {
public static void main(String[] args) throws Exception {
// 変数にnullをセット
String str = null;
}
}
NullPointerException
nullが設定された変数で、メソッドの呼び出しを行うとNullPointerExceptionが発生します。
public class Main {
public static void main(String[] args) throws Exception {
// 変数にnullをセット
String str = null;
}
}
null判定をしてからメソッドを呼び出す
NullPointerExceptionが発生すると、当然ながらエラーで最悪の場合、アプリケーションが以上終了します。
そのため、一般的にnullが格納される可能性がある変数のメソッド呼び出しは、事前に中身がnullでないかチェックしてから呼び出しをおこない、NullPointerExceptionを回避します。
public class Main {
public static void main(String[] args) throws Exception {
String str = null;
// 変数 strが null以外の時だけ toUpperCase()メソッドを呼び出し
if (str != null) {
System.out.println( str.toUpperCase() );
} else {
System.out.println( "変数strはnullです" );
}
}
}
上のコードを実行すると次のような結果になります。
【実行結果】
変数strはnullです
intやcharでもnullを扱いたい
冒頭でも伝えましたが、プリミティブ型のint型やchar型の変数には、nullを入れることはできません。(以下のようにコンパイルエラーになります)
int a = null;
【コンパイルエラー】
// Main.java:3: error: incompatible types: <null> cannot be converted to int
// int a = null;
// ^
intやcharでもnullを扱いたい場合は、それをラップするIntegerやCharacterなどの参照型のラッパークラスを使用します。
各プリミティブ型に対応するラッパークラスの対応は次の表の通りです。
プリミティブ型 | ラッパークラス |
---|---|
boolean | Boolean |
byte | Byte |
char | Character |
short | Short |
int | Integer |
float | Float |
long | Long |
double | Double |
実際にintのラッパークラスであるInteger型の変数にnullをセットしてみましょう。
public class Main {
public static void main(String[] args) throws Exception {
Integer a = null;
if (a == null) {
System.out.println("変数aはnullです");
}
}
}
【実行結果】
変数aはnullです
nullと空文字(Empty)は異なるもの
nullと空文字(Empty)は似ているようで同じものと勘違いしてしまいそうですが、次のリストのように明確な違いがあり、異なるものです。
- NULL:何も定義されていない(何も入っていない)状態
- 空文字:長さ0の文字列
実際にnullと空文字が格納された変数を作成して、null判定を行うサンプルコードを作成してみましょう。
public class Main {
public static void main(String[] args) throws Exception {
String str1 = null; // nullを格納した変数
String str2 = ""; // 空文字を格納した変数
if (str1 == null) System.out.println("str1はnullです");
if (str2 == null) System.out.println("str2はnullです");
}
}
上のコードを実行すると次のような結果となります。
【実行結果】
str1はnullです
str2の判定で、null以外と判定されてコンソールに何も出力されていないことから、空文字はnullとは異なるものだと言うことがわかります。
Optionalを使ったnullの新しい扱い方
Java 8でjava.util.Optionalクラスが追加され、nullの新しい扱い方ができるようになりました。
java.util.Optionalは、nullの可能性がある変数をうまく取り扱うクラスで、例えば次のコードのように、nullの判定とnullでない場合のメソッド呼び出しを1行で記述できたりします。
opt.ifPresent(f -> System.out.println("値がnull以外のときだけ呼び出される処理"));
今回は、簡単にOptionalクラスの代表的な使い方を紹介します。
「Optional.ifPresent」メソッド
値がnull以外の場合のみ、引数で指定しらラムダ式が実行されるメソッドです。
import java.util.Optional;
public class Main {
public static void main(String[] args) throws Exception {
String str = "test";
final Optional<String> opt = Optional.ofNullable(str);
opt.ifPresent(f -> System.out.println("strがnull以外のときだけ呼び出されます"));
}
}
「Optional.ifPresentOrElse」メソッド
値がnull以外の場合のみ、引数で指定しらラムダ式が実行されるメソッドです。
import java.util.Optional;
public class Main {
public static void main(String[] args) throws Exception {
String str = "test";
final Optional<String> opt = Optional.ofNullable(str);
opt.ifPresentOrElse(
e -> System.out.println("strがnull以外のときに呼び出されます"),
() -> System.out.println("strがnullのときに呼び出されます"));
}
}
nullを理解してバグの起きないプログラムを作ろう
nullと一体何なのかという話から、nullを判定する方法や、新しいOptionalクラスの使い方まで紹介してきました。
nullを正しく理解し、NullPointerExceptionなどのエラーが発生しないプログラムを作成しましょう。
java.util.Optional.ifPresentOrElseメソッドは、Java 9で追加されたAPIです。Java 8のjava.util.Optionalクラスにはメソッドは存在しないため注意しましょう。