Kodrill

例外処理

Java SE 17 Silver (1Z0-825-JPN) 試験

チェック例外・非チェック例外・エラー/try-catch/try-with-resources/カスタム例外/multi-catch

問題数
20 問
合格ライン
65%
実行して確認済み
18 問
この分野の要点を読む6 章・約 16 分。実行して確かめたコード例と、試験でよくある引っかけをまとめています

ログインなしで試す

無料の 5 問を、1問ごとに正誤と解説を見ながら解けます。解答は保存されません。

5 問を試す

無料登録して学習を記録する

学習履歴・ダッシュボード・ブックマーク・模試モードが使えます。

★ 残り 15 問はプレミアム会員限定です

無料プランでは先頭 5 問まで解けます。プレミアムなら全問題・苦手問題の復習・広告非表示が使えます。
料金プランを見る

問題と解説を見る (無料)

登録しなくても、次の5問は問題文と解説をそのまま読めます。

例外処理の要点

内容の確認日: 2026-10-04

この分野では、例外が「どこで発生し、どの catch で捕まり、何が出力されるか」を追う問題と、例外処理の書き方がコンパイルできるかを判断する問題が出ます。finally と return の組み合わせや、try-with-resources の close の順番は、特によく問われます。

出題項目は「例外処理の仕組みとチェック例外、非チェック例外、エラーの違い」「try-catch 文による例外処理」「try-with-resources 文による例外処理」「multi-catch 句の使用」「カスタム例外の作成」の 5 つです。

例外の種類

例外のクラスは Throwable を頂点に、次のように分かれます。

・Error: JVM のメモリ不足 (OutOfMemoryError) や、終わりのない再帰によるスタックのあふれ (StackOverflowError) など、プログラムで回復できない重大な問題 ・Exception のうち RuntimeException とそのサブクラス: 非チェック例外。NullPointerException・ArithmeticException・IllegalArgumentException など ・それ以外の Exception のサブクラス: チェック例外。IOException・ClassNotFoundException など

チェック例外を投げる可能性のあるメソッドを呼ぶときは、try-catch で捕まえるか、自分のメソッドにも throws を書いて呼び出し元に任せるか、どちらかをしないとコンパイルエラーになります。非チェック例外とエラーには、この義務はありません。

Main.java
import java.io.IOException;​public class Main {    static void load() throws IOException {        throw new IOException("読み込み失敗");    }​    public static void main(String[] args) {        load();    }}
ターミナル
javac Main.java

コンパイルエラー (9 行目): チェック例外 IOException を catch も throws もしていない

Integer.parseInt("abc") が投げる NumberFormatException は、IllegalArgumentException のサブクラスで、非チェック例外です。

try-catch-finally の流れ

try ブロックの途中で例外が発生すると、残りの処理は飛ばされ、例外の型に合う catch ブロックに移ります。catch は上から順に判定され、最初に合ったもの 1 つだけが実行されます。そのため、サブクラスの例外の catch を、スーパークラスの catch より後ろに書くと、到達できない catch としてコンパイルエラーです。

Main.java
public class Main {    public static void main(String[] args) {        try {            int[] a = new int[1];            a[2] = 1;        } catch (RuntimeException e) {            System.out.println("Runtime");        } catch (ArrayIndexOutOfBoundsException e) {            System.out.println("Index");        }    }}
ターミナル
javac Main.java

コンパイルエラー (8 行目): ArrayIndexOutOfBoundsException は、先に書いた RuntimeException の catch で必ず捕まるので到達できない

同じように、try ブロックの中で発生する可能性のないチェック例外を catch に書くと、コンパイルエラーになります (Exception や非チェック例外の catch は書けます)。

finally ブロックは、例外が発生してもしなくても、try や catch の中で return しても、必ず実行されます。ただし、return で返す値は return 文を実行した時点で決まっているので、finally の中で変数を変えても戻り値は変わりません。

Main.java
public class Main {    static int test() {        int x = 1;        try {            return x;        } finally {            x = 2;            System.out.println("finally: x = " + x);        }    }​    public static void main(String[] args) {        System.out.println("戻り値: " + test());    }}
ターミナル
java Main
finally: x = 2
戻り値: 1

catch ブロックの中で新しい例外が発生した場合、同じ try に付いた他の catch では捕まりません。finally を実行した後、例外は呼び出し元に伝わります。

Main.java
public class Main {    public static void main(String[] args) {        try {            Object o = "text";            Integer n = (Integer) o;            System.out.println("A");        } catch (ClassCastException e) {            System.out.println("B");            throw new IllegalStateException("catch の中で発生");        } catch (IllegalStateException e) {            System.out.println("C");        } finally {            System.out.println("D");        }    }}
ターミナル
java Main
B
D

実行時に例外が発生: IllegalStateException

try-with-resources

try (リソースの宣言) { ... } の形の try-with-resources 文を使うと、AutoCloseable を実装したリソースの close が自動で呼ばれます。主なルールは次のとおりです。

・リソースは宣言した順に初期化され、try ブロックを抜けるときに逆の順番で close される ・close は catch・finally より前に呼ばれる ・try ブロックの中で return しても、メソッドを抜ける前に close される ・Java SE 9 からは、try の外で宣言した変数を try (r) のように指定できる。ただし final か、実質的に final (代入し直していない) な変数に限る

Main.java
class Resource implements AutoCloseable {    private final String name;​    Resource(String name) {        this.name = name;        System.out.println("open " + name);    }​    @Override    public void close() {        System.out.println("close " + name);    }}​public class Main {    public static void main(String[] args) {        try (Resource a = new Resource("A"); Resource b = new Resource("B")) {            System.out.println("処理");            throw new RuntimeException("失敗");        } catch (RuntimeException e) {            System.out.println("catch: " + e.getMessage());        } finally {            System.out.println("finally");        }    }}
ターミナル
java Main
open A
open B
処理
close B
close A
catch: 失敗
finally

try ブロックで例外が発生した後、close でも例外が発生した場合、catch に渡されるのは try ブロックの例外です。close の例外は抑制された例外として、getSuppressed() で取り出せます。

Main.java
class Faulty implements AutoCloseable {    @Override    public void close() throws Exception {        throw new Exception("close で失敗");    }}​public class Main {    public static void main(String[] args) {        try (Faulty f = new Faulty()) {            throw new IllegalStateException("本体で失敗");        } catch (Exception e) {            System.out.println(e.getMessage());            System.out.println(e.getSuppressed()[0].getMessage());        }    }}
ターミナル
java Main
本体で失敗
close で失敗

multi-catch 句

catch (IllegalArgumentException | IndexOutOfBoundsException e) のように | で区切ると、複数の例外を 1 つの catch で捕まえられます (multi-catch)。次の 2 つの制限があります。

・継承関係にある例外は並べられない (スーパークラス側だけで足りるため) ・例外の変数は暗黙的に final で、別の値を代入できない

Main.java
public class Main {    public static void main(String[] args) {        try {            Integer.parseInt("x");        } catch (NumberFormatException | IllegalArgumentException e) {            System.out.println("変換できません");        }    }}
ターミナル
javac Main.java

コンパイルエラー (5 行目): NumberFormatException は IllegalArgumentException のサブクラスなので、multi-catch に並べられない

カスタム例外

Exception や RuntimeException を継承すると、独自の例外クラス (カスタム例外) を作れます。Exception を継承すればチェック例外、RuntimeException を継承すれば非チェック例外になります。コンストラクタで super(message) を呼ぶと、getMessage() でそのメッセージを取り出せます。

Main.java
class InsufficientBalanceException extends Exception {    InsufficientBalanceException(String message) {        super(message);    }}​class Wallet {    private int balance = 500;​    void pay(int amount) throws InsufficientBalanceException {        if (amount > balance) {            throw new InsufficientBalanceException("残高不足: " + (amount - balance) + " 円足りません");        }        balance -= amount;    }}​public class Main {    public static void main(String[] args) {        Wallet wallet = new Wallet();        try {            wallet.pay(300);            wallet.pay(300);            System.out.println("支払い完了");        } catch (InsufficientBalanceException e) {            System.out.println(e.getMessage());        }    }}
ターミナル
java Main
残高不足: 100 円足りません

1 回目の支払いで残高は 200 円になり、2 回目で例外が発生します。InsufficientBalanceException はチェック例外なので、pay には throws が、呼び出し側には try-catch が必要です。

試験でよくある引っかけ

  • チェック例外の扱い忘れ

    チェック例外を投げるメソッドを呼ぶときは、try-catch か throws が必要です。どちらもないとコンパイルエラーです。

  • catch の順番

    スーパークラスの例外の catch を先に書くと、後ろのサブクラスの catch に到達できずコンパイルエラーです。

  • finally と戻り値

    try で return x; した後に finally で x を変えても、戻り値は変わりません。

  • catch の中の例外

    catch の中で発生した例外は、同じ try の他の catch では捕まりません。finally の後に呼び出し元へ伝わります。

  • close の順番

    try-with-resources のリソースは、宣言と逆の順番で、catch・finally より前に close されます。

  • multi-catch の継承関係

    FileNotFoundException | IOException のように継承関係にある例外は並べられません。

問題で確認する

この分野の問題を、解説つきで読めます (登録不要)。

出典・参考

コード例は、試験の対象バージョンで実際にコンパイル・実行して結果を確認しています。