例外クラスの階層構造
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 59/87。
Java の例外処理システムは、Throwable クラスをルートとする、よく整理されたクラス階層に基づいて構築されています。この階層を理解すると、例外をより効果的に捕捉して処理できるようになります。
最上位にあるのは、すべての例外とエラーの親である Throwable です。直接のサブクラスは2つあります。
Throwable
├── Error // 深刻な問題(これらはキャッチしないでください)
└── Exception // 回復可能な問題
└── RuntimeException // 非チェック例外Error は、アプリケーションが処理しようとすべきではない重大な問題を表します。たとえば、OutOfMemoryError や StackOverflowError です。これらは、JVM 自体に根本的な問題があることを示します。
Exception は、最も頻繁に扱うことになるブランチです。これは、検査例外(Exception の直接のサブクラス)と非検査例外(RuntimeException のサブクラス)の2つのカテゴリに分かれます。
// 一般的な例外クラス
Exception
├── IOException // ファイル/ネットワークの問題
├── SQLException // データベースの問題
└── RuntimeException
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── IllegalArgumentExceptionexceptions は classes なので、継承ルールに従います。親の exceptions 型を catch すると、そのすべての子も catch します。
try {
// いくつかのコード
} catch (Exception e) {
// すべての例外をキャッチする(通常は広すぎる)
}try {
// いくつかのコード
} catch (RuntimeException e) {
// Catches only runtime exceptions and subclasses
}この hierarchy により、エラーを処理する際に必要に応じて具体的にも一般的にもでき、独自のカスタム exceptions を作成するための基盤となります。
チャレンジ
簡単Java の exception hierarchy が実際にどのように機能するかを示す exception analyzer を構築しましょう!異なる specificity のレベルで exception を捕捉し、どの型が捕捉されたかを報告するシステムを作成します。
コードを 3 つのファイルに分けて構成します。
ExceptionThrower.java:入力に基づいてさまざまな種類の exception を発生させられる class を作成します。この class には、次の 3 つの static メソッドを用意します。triggerRuntime(String type)- type 文字列に基づいて、異なる runtime exception を throw します。- type が
"null"の場合、メッセージ"Null value encountered"を持つNullPointerExceptionを throw します - type が
"index"の場合、メッセージ"Invalid index"を持つArrayIndexOutOfBoundsExceptionを throw します - type が
"argument"の場合、メッセージ"Bad argument"を持つIllegalArgumentExceptionを throw します
triggerArithmetic()- メッセージ"Division error"を持つArithmeticExceptionを throw しますtriggerGeneric()- メッセージ"Generic runtime error"を持つIllegalStateExceptionを throw します(その hierarchy は Exception > RuntimeException > IllegalStateException です)- type が
ExceptionAnalyzer.java:異なる hierarchy のレベルで exception を捕捉し、何が捕捉されたかを特定する class を作成します。次の static メソッドを含めます。analyzeSpecific(String type)-ExceptionThrower.triggerRuntime(type)を try ブロック内で呼び出します。NullPointerException、ArrayIndexOutOfBoundsException、IllegalArgumentException用に個別の catch ブロックを使用します。それぞれについて、Caught specific: [exception class simple name]に続けてMessage: [exception message]を出力します。analyzeWithParent()-ExceptionThrower.triggerArithmetic()を try ブロック内で呼び出します。RuntimeException(parent 型)を使って捕捉します。Caught via parent: RuntimeExceptionに続けてActual type: [exception class simple name]を出力します。analyzeWithGrandparent()-ExceptionThrower.triggerGeneric()を try ブロック内で呼び出します。hierarchy のさらに上位にあるExceptionを使って捕捉します。Caught via grandparent: Exceptionに続けてActual type: [exception class simple name]を出力します。Main.java:exception analyzer をまとめて動作させます!入力として 1 つの exception type 文字列("null"、"index"、または"argument"のいずれか)を受け取ります。まず、
=== Specific Catch ===を出力し、入力を使ってanalyzeSpecificを呼び出します。次に空行を出力し、
=== Parent Catch ===を出力して、analyzeWithParentを呼び出します。最後に空行を出力し、
=== Grandparent Catch ===を出力して、analyzeWithGrandparentを呼び出します。
発生させる exception type("null"、"index"、または "argument")を 1 つ入力として受け取ります。
e.getClass().getSimpleName() を使用して exception の class 名を取得し、e.getMessage() を使用してそのメッセージを取得します。この challenge では、parent exception type を捕捉すると、そのすべての子も捕捉されることを示します。これは、exception handling をどの程度具体的にするかを決める際の重要な概念です!
自分で試してみよう
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String type = scanner.nextLine();
// TODO: Print "=== Specific Catch ===" and call ExceptionAnalyzer.analyzeSpecific(type)
// TODO: 空行を出力し、次に "=== Parent Catch ===" を出力してから、ExceptionAnalyzer.analyzeWithParent() を呼び出す
// TODO: Print a blank line, then "=== Grandparent Catch ===", then call ExceptionAnalyzer.analyzeWithGrandparent()
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造自分で練習してみよう: Javaオンラインコンパイラ