Programmingバックエンド開発者

Javaにおけるチェック例外と非チェック例外の違いは何ですか?エラー処理を正しく設計する方法と、それらの使用時に避けるべきエラーは何ですか?

Hintsage AIアシスタントで面接を突破

回答

Javaでは、例外はチェック例外(checked)と非チェック例外(unchecked)に分けられます。

  • チェック例外Exceptionから派生していますが、RuntimeExceptionからは派生していません。コンパイラーは、これらを明示的にtry-catchで扱うか、throwsで宣言することを要求します。
  • 非チェック例外RuntimeExceptionから派生しています。コンパイラーはそれらを必ずしも処理する必要はありません。
public void readFile(String file) throws IOException { /* ... */ } // チェック例外 public void divide(int a, int b) { int res = a/b; } // 非チェック例外 (ArithmeticException)

主なポイントは、チェック例外は期待される回復可能な状況(例えば、入出力エラー)のために使用されるのに対し、非チェック例外はプログラムのロジックのエラーや回復できないクリティカルな状況(例えば、NullPointerException)のために使用されるということです。

アイデアの問い

質問: メソッドが非チェック例外をスローする可能性があるとき、それを処理する必要がありますか?またはthrowsで宣言する必要がありますか?

回答: いいえ。回復不能(非チェック)例外をチェックまたは宣言する必要はありません。処理はあなたの裁量に任されています;try-catchを使用することもできますが、一般的にはグローバルハンドラーまで「落ちる」ことを許可します。

public void foo() { throw new IllegalArgumentException(); } // 処理や宣言を必要としません

知識不足による実際のエラーの例


銀行APIプロジェクトで、入出力エラーを処理する際にチェック例外の代わりにRuntimeExceptionをスローした結果、クライアントはそれらを処理する必要がなくなり、サーバー接続の喪失時に不正な動作を引き起こし、アプリケーションがユーザーに通知せずに「落ちる」ことになりました。


開発者がメソッドのシグネチャに不必要に多くのthrows Exceptionを宣言したため、上記の使用されるすべてのメソッドがtry-catchまたは別のthrowsを使用する必要がありました。これによりコードが散らかり、可読性が低下し、リファクタリングが困難になりました。


あるマイクロサービスでは、すべての例外を一般的なcatch (Exception e)で捕捉していました。これにより、非チェック例外(例えば、NullPointerException)も捕捉され、重要なエラーが「静かに」無視される結果となり、サービスが不正なデータで動作することになりました。