SJ blog
Java
Z

信頼度ランク

S 公式ソース確認済み
A 成功実績多数・失敗例少数
B 賛否両論
C 動作未確認・セキュリティリスク高
Z 個人所感

NullPointerExceptionを確実に解決・予防する方法

JavaのNullPointerExceptionの原因パターンを分類し、Java 14以降のHelpful NullPointerExceptionsやOptionalを使った予防法まで解説します。

一言結論

NPEの根本対策はOptionalやObjects.requireNonNullで設計段階でnullを排除することで、Java 14以降のHelpful NPEは「どのチェーンでnullか」をスタックトレースに明示するため原因特定が格段に速い。

NullPointerException とは

null を参照しようとしたときに発生する例外です。Java で最も頻繁に遭遇するエラーの一つです。

String name = null;
System.out.println(name.length()); // NullPointerException!

よくある発生パターン

パターン1: 初期化し忘れ

List<String> items;  // null のまま
items.add("hello");  // NPE

修正:

List<String> items = new ArrayList<>();

パターン2: メソッドの戻り値が null

Map<String, String> map = new HashMap<>();
String value = map.get("key");  // キーがなければ null
System.out.println(value.toUpperCase());  // NPE

修正:

String value = map.getOrDefault("key", "");
// または
String value = map.get("key");
if (value != null) {
    System.out.println(value.toUpperCase());
}

パターン3: 配列の要素が null

String[] names = new String[3];
System.out.println(names[0].length());  // NPE(要素はまだ null)

修正:

String[] names = {"Alice", "Bob", "Charlie"};

パターン4: メソッドチェーン

String city = user.getAddress().getCity();  // address が null なら NPE

修正:

String city = Optional.ofNullable(user)
    .map(User::getAddress)
    .map(Address::getCity)
    .orElse("Unknown");

Java 14以降: Helpful NullPointerExceptions

Java 14 から NPE のメッセージが詳しくなりました。

Java 13以前:

Exception in thread "main" java.lang.NullPointerException

Java 14以降:

Cannot invoke "String.length()" because "name" is null

有効化(Java 14〜17):

java -XX:+ShowCodeDetailsInExceptionMessages MyApp

Java 17以降はデフォルトで有効です。

Optional を使った予防

Optional はnullになりうる値をラップするコンテナです。

// 返り値をOptionalにする
public Optional<User> findUserById(int id) {
    User user = database.find(id);
    return Optional.ofNullable(user);
}

// 呼び出し側
findUserById(42)
    .map(User::getName)
    .ifPresent(name -> System.out.println("User: " + name));

// デフォルト値を使う
String name = findUserById(42)
    .map(User::getName)
    .orElse("匿名");

Objects.requireNonNull で引数を検証

public void process(String data) {
    Objects.requireNonNull(data, "data must not be null");
    // data が null なら NPE がここで発生(スタックトレースが明確になる)
    data.toUpperCase();
}

Eclipseの@Nullableアノテーション活用

Eclipse は @Nullable/@NonNull アノテーションでnullチェックを静的解析できます。

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;

public @Nullable String findName(int id) {
    // nullable な返り値
}

public void greet(@NonNull String name) {
    // name は non-null であることが保証される
}

Preferences > Java > Compiler > Errors/Warnings > Null analysis で設定します。

チェックリスト

  • メソッドの戻り値が null になりうるか確認したか
  • コレクションの要素を取り出す際にnullチェックをしているか
  • フィールドが初期化されているか
  • 外部入力(ユーザー入力、APIレスポンスなど)をnullチェックしているか
  • Optional を適切に使っているか

NPE は「予防」がベストです。コードレビュー時にnullになりうる箇所を意識するだけで大幅に減らせます。