Java

Javaのnullチェック入門

AIによる要約

Javaのnullチェックは、すべての変数に機械的に入れればよいものではありません。大事なのは、必須の値は入口で弾き、任意の値は安全に扱い、NullPointerExceptionの原因を追いやすくすることです。この記事では、初学者向けの基本とSES/SIer現場でレビューされやすい観点を整理します。

新人SE
新人SE
nullチェックって、とりあえず全部の変数に入れておけば安全なんですか?
ポンコツSE
ポンコツSE
全部に入れると、逆に何が必須なのか分かりにくくなります。現場では「どこでnullを許すのか」を決めることが大事です。

Javaの現場でかなりよく見るエラーが、NullPointerExceptionです。

初学者のうちは、エラーが怖くてあちこちにif (value != null)を書きたくなります。ただ、レビューではその書き方も指摘されることがあります。

この記事のポイント

  • nullは「空文字」ではなく「参照先がない」状態
  • 必須項目は処理の入口で早めに弾く
  • 比較だけならObjects.equalsが安全な場面がある
  • nullチェックを増やすより、nullの流入地点を減らす方が読みやすい

まずnullは空文字ではない

nullは、文字数0の文字列ではありません。「値が入っていない」というより、Javaでは「参照先がない」と捉える方が近いです。

String name = null;

System.out.println(name.length()); // NullPointerException

このコードは、nameの先にStringオブジェクトが存在しないため、length()を呼び出せません。

現場で困るのはnullの出どころが曖昧なコード

SIerの業務システムでは、画面入力、DB、外部API、CSVなど、さまざまな場所から値が入ってきます。問題は、どこからnullが来るのか分からないまま処理が進むことです。

深い処理の途中でNPEが出ると、原因調査に時間がかかります。だからこそ、必須の値は入口で止めるのが基本です。

public void register(String userId) {
    Objects.requireNonNull(userId, "userId must not be null");

    // ここから下はuserIdが必ずある前提で読める
    userRepository.save(userId);
}

比較だけならObjects.equalsを使う

文字列やIDを比較するだけなら、Objects.equalsが便利です。左右どちらかがnullでも安全に比較できます。

if (Objects.equals(inputStatus, "ACTIVE")) {
    System.out.println("有効ユーザーです");
}

ただし、Objects.equalsはnullを許して比較するための道具です。必須値なのにnullが来ている場合は、比較でごまかさず入口で弾いた方がよいです。

レビューで見られるポイント

nullチェックの確認リスト

  • 必須項目なのに、処理の奥で初めてnullチェックしていないか
  • nullの場合に処理を続けるべきか、止めるべきかが明確か
  • 同じ変数に何度もnullチェックを書いていないか
  • エラーメッセージから原因項目が分かるか

レビューでは、単にNPEを避けているかだけでなく、コードを読む人が前提条件を追えるかも見られます。

現場ではどこからnullが入ってくるのか

現場で null がやっかいなのは、コードを書いた本人が思っていない場所から入ってくることです。特にSES/SIerの業務システムでは、値の入口が多く、画面、DB、CSV、外部API、バッチ連携などが混ざります。

  • 画面の任意入力欄が未入力だった
  • DBの古いデータだけ一部カラムが null だった
  • 外部APIのレスポンスで、仕様上は必須のはずの項目が欠けていた
  • CSVの空欄を空文字ではなく null として読み込んでいた

レビューでは、「この値はどこから来るのか」「必須なのか任意なのか」「nullの場合は処理を止めるのか続けるのか」を説明できるかが見られます。

必須値と任意値で書き方を分ける

すべての値を同じように if (value != null) で囲むと、何が必須で何が任意なのか分からなくなります。必須なら入口で止め、任意なら表示や処理のルールを決めます。

public void register(UserRequest request) {
    Objects.requireNonNull(request.getUserId(), "userId is required");

    String nickname = request.getNickname();
    String displayName = nickname != null ? nickname : "未設定";

    userRepository.save(request.getUserId(), displayName);
}

この例では、userId は必須なので処理の入口で止めています。一方、nickname は任意なので、nullでも処理を続けられるように表示用の値へ変換しています。

// レビューコメント例
// userIdは必須項目なので、途中でnullチェックするより入口で弾いてください。
// nicknameは任意項目なので、null時の表示仕様をコード上で分かるようにしてください。

null判断の現場ルール

  • 必須値は入口で止める
  • 任意値はデフォルト値や未表示などの扱いを決める
  • nullチェックの場所を散らばらせない
  • NPEが出たときに、どの入力が原因か追えるメッセージにする

まとめ

nullチェックは、数を増やせばよいものではありません。必須値は入口で弾き、任意値は安全なAPIで扱い、nullの意味をコードから分かるようにするのが現場向きです。

-Java
-, , , ,