はじめに
Nullチェックを削除する方法はいくつかあります。最適な方法を使用してください。
- NullObjectパターン
- オブジェクト指向プログラミングが使えれば、どの言語でも実現可能
- Null合体演算子
- 言語仕様にNull合体演算子があれば可能
- その他の方法
- Javaの場合は
Optional
を使用
- Javaの場合は
NullObjectパターン
NullObjectパターンを使用することで、Nullチェックのif文を削除できます。
クラス図
コード例
次にように作成します。
何もない(本例では職種がない)ことを表すサブクラスであるNullEmployeeクラスを作成します。
サブクラスのメソッド(本例ではgetTypeNameメソッド)は呼ばれても何も処理しないようにします
CreatorクラスのfactoryMethodにおいて、不正なパラメータを受け取った場合は、NullEmployeeクラスを返します。
呼び出し元関数のおいて、Nullチェックのif文を削除します
- NullEmployeeクラスのインスタンスが存在するため、NullPointerExceptionの例外が発生しません。
本記事に記載されていない他のクラス(Salesman, Engineer, Manager, Employee)のコードは、以下の記事を参照ください。
[NullEmployee .java]
// 具象クラス public class NullEmployee extends Employee { public NullEmployee(int typeId) { _typeId = typeId; } @Override public int getTypeId() { return _typeId; } @Override public String getTypeName() { // Nullオブジェクトであるため、処理が空っぽの状態とする return ""; } }
[CreatorEmployee.java]
// 本クラスは継承を禁止するため、final修飾子を付与します public final class CreatorEmployee { // 本例では、定数の定義はCreatorEmployeeクラスが持ちます // もし、列挙型(Enum)を使いたいなら、以下のサイトを参考にしてください // https://qiita.com/KeithYokoma/items/9681b130ea132cfad64d public static final int ENGINEER = 0; public static final int SALESMAN = 1; public static final int MANAGER = 2; public static final int ILLEGAL_EMPLOYEE = -1; // コンストラクタをprivateにすることで、インスタンス化を禁止させましょう private CreatorEmployee(){ } // factoryMethodメソッドの役割は与えられたパラメータによって生成するインスタンスを切り替えること public static Employee factoryMethod(int type) { switch(type) { case ENGINEER: return new Engineer(ENGINEER); case SALESMAN: return new Salesman(SALESMAN); case MANAGER: return new Manager(MANAGER); default: System.out.println("Error!! Illegal Parameter."); return new NullEmployee(ILLEGAL_EMPLOYEE); } } }
[Main.java]
import java.util.*; public class Main { public static void main(String[] args) throws Exception { // (1) インスタンスを生成 // (2) 関数に作成したインスタンスを渡す Employee engineer = createEmployee(CreatorEmployee.ENGINEER); showTypeName(engineer); showId(engineer); Employee salesman = createEmployee(CreatorEmployee.SALESMAN); showTypeName(salesman); showId(salesman); Employee manager = createEmployee(CreatorEmployee.MANAGER); showTypeName(manager); showId(manager); Employee nullEmployee = createEmployee(-9999); // 不正値を入力する showTypeName(nullEmployee); showId(nullEmployee); } public static Employee createEmployee(int type) { return CreatorEmployee.factoryMethod(type); } public static void showId(Employee employ) { // Nullオブジェクト適用により、null比較のif文がなくなりました。 System.out.println(employ.getTypeName()); } public static void showTypeName(Employee employ) { // Nullオブジェクト適用により、null比較のif文がなくなりました。 System.out.println(employ.getTypeId()); } }
0 Engineer 1 Salesman 2 Manager Error!! Illegal Parameter. -1
null合体演算子
言語使用に、NullObjectパターンを使用するのではなく、言語使用として、NullObjectパターンを使用しなくともNullPointerException例外を回避できる仕組みがあります。
C#では「null合体演算子」(null coalescing operator、coalesceは「合体する」という意味の動詞)を使うと、nullチェックのif文を削除できます。
以下に、コード例を記載します。
[適用前]
public class Test{ public static void Main(){ string documentTitle = null; string initialTitle = "報告書"; if (documentTitle == null) { documentTitle = initialTitle; } System.Console.WriteLine(documentTitle); } }
報告書
Null合体演算子(C#では??)を使うと以下のように記載できます。これにより、Nullチェックのif文を削除できました
[適用後]
public class Test{ public static void Main(){ string documentTitle = null; string initialTitle = "報告書"; string fileName = documentTitle ?? initialTitle; System.Console.WriteLine(fileName); } }
報告書
その他の方法
Java言語の場合はOptionalを使うことで、NullPointerException例外を回避できそうです。
- Java 8 "Optional" ~ これからのnullとの付き合い方 ~
あとがき
NullObjectパターンを使用しなくともNullPointerException例外を回避できる言語仕様があれば、積極的に使うべきだと思います。
NullObjectパターンは、あまり使われなくなりそうです。