2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java Silver対策】例外処理

2
Posted at

Java Silver試験で頻出の「例外処理」に関する問題を10問収録しました。try-catch-finally、検査例外と非検査例外、throws宣言、try-with-resources、例外の継承階層、マルチキャッチなど、試験で問われやすいポイントを網羅しています。


問題1 ⭐(基本)

次のコードをコンパイル・実行すると、どうなりますか?

public class Main {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Caught: " + e.getMessage());
        } finally {
            System.out.println("Finally block");
        }
    }
}
  • A. Result: 0Finally block
  • B. Caught: / by zeroFinally block
  • C. Caught: / by zero
  • D. Finally blockのみ
解答と解説

正解: B

10 / 0ArithmeticExceptionをスローします。tryブロック内で例外が発生すると、それ以降の文(System.out.println("Result: " + result))は実行されません。

catchブロックで例外が捕捉され、e.getMessage()"/ by zero"を返します。finallyブロックは例外の有無にかかわらず必ず実行されます。

finallyブロックが実行されないのは、System.exit()が呼ばれた場合やJVMが異常終了した場合のみです。


問題2 ⭐⭐(応用)

次のコードをコンパイル・実行すると、どうなりますか?

public class Main {
    public static void main(String[] args) {
        System.out.println(getValue());
    }

    static int getValue() {
        try {
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            return 3;
        }
    }
}
  • A. 1
  • B. 2
  • C. 3
  • D. コンパイルエラー
解答と解説

正解: C

finallyブロック内のreturnは、trycatchブロック内のreturn上書きします。tryブロックでreturn 1が実行されようとしますが、finallyブロックのreturn 3が最終的に実行されるため、メソッドは3を返します。

finallyブロック内でreturnを使うことは推奨されません。予期しない動作の原因になり、try/catchでスローされた例外も握りつぶしてしまいます。


問題3 ⭐⭐(応用)

次のコードをコンパイルすると、どうなりますか?

import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("Hello");
        } catch (IOException e) {
            System.out.println("Caught IOException");
        }
    }
}
  • A. Helloが出力される
  • B. コンパイルエラー: IOExceptiontryブロックからスローされない
  • C. HelloCaught IOException
  • D. 実行時エラー
解答と解説

正解: B

検査例外(IOExceptionなど)をcatchする場合、コンパイラはtryブロック内のコードがその例外をスローする可能性があるかチェックします。System.out.println("Hello")IOExceptionをスローしないため、到達不能なcatchブロックとしてコンパイルエラーになります。

ただし、非検査例外(RuntimeExceptionやそのサブクラス)のcatchは、tryブロックがその例外をスローしなくてもコンパイルエラーになりません。

// これはコンパイル可能
try {
    System.out.println("Hello");
} catch (RuntimeException e) { // OK
    System.out.println("Caught");
}

問題4 ⭐⭐⭐(チャレンジ)

次のコードをコンパイル・実行すると、どうなりますか?

public class Main {
    public static void main(String[] args) {
        try {
            throw new RuntimeException("first");
        } catch (RuntimeException e) {
            System.out.println(e.getMessage());
            throw new RuntimeException("second");
        } finally {
            System.out.println("finally");
        }
    }
}
  • A. firstfinallyRuntimeException: secondがスローされる
  • B. firstRuntimeException: secondがスローされる
  • C. firstfinally
  • D. コンパイルエラー
解答と解説

正解: A

実行順序:

  1. tryブロックでRuntimeException("first")がスローされる
  2. catchブロックで捕捉され、"first"が出力される
  3. catchブロックでRuntimeException("second")がスローされる
  4. ただしfinallyブロックが先に実行され、"finally"が出力される
  5. finallyブロック完了後、catchブロックからのRuntimeException("second")がスローされる

catchブロックで例外をスローしても、finallyブロックは必ず実行されます。mainメソッドで例外が処理されないため、最終的にスタックトレースが出力されます。


問題5 ⭐(基本)

次のコードをコンパイルすると、どうなりますか?

import java.io.IOException;

public class Main {
    static void riskyMethod() throws IOException {
        throw new IOException("File not found");
    }

    public static void main(String[] args) {
        riskyMethod();
        System.out.println("Done");
    }
}
  • A. File not foundが出力される
  • B. Doneが出力される
  • C. コンパイルエラー: mainで検査例外が処理されていない
  • D. 実行時エラー
解答と解説

正解: C

riskyMethod()throws IOExceptionを宣言しています。IOExceptionは検査例外(ExceptionのサブクラスでRuntimeExceptionではない)なので、呼び出し側は以下のいずれかを行う必要があります:

  1. try-catchで捕捉する
  2. throwsで上位に伝播させる

mainメソッドはどちらも行っていないため、コンパイルエラーになります。

修正例:

public static void main(String[] args) {
    try {
        riskyMethod();
    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
    System.out.println("Done");
}

問題6 ⭐⭐(応用)

次のコードをコンパイル・実行すると、どうなりますか?

public class Main {
    public static void main(String[] args) {
        try {
            String s = null;
            System.out.println(s.length());
        } catch (NullPointerException | ArithmeticException e) {
            System.out.println("Caught: " + e.getClass().getSimpleName());
        }
    }
}
  • A. Caught: NullPointerException
  • B. Caught: ArithmeticException
  • C. コンパイルエラー(マルチキャッチが不正)
  • D. 実行時エラー
解答と解説

正解: A

snullなのでs.length()NullPointerExceptionをスローします。マルチキャッチ(|で複数の例外型を指定)で捕捉されます。

マルチキャッチのルール:

  • |で区切って複数の例外型を指定できる
  • マルチキャッチの変数eは暗黙的にfinal(再代入不可)
  • 継承関係にある例外を同時に指定できない(例: IOException | Exceptionはコンパイルエラー)
// コンパイルエラーの例
catch (IOException | Exception e) { } // ExceptionはIOExceptionの親クラス

// マルチキャッチの変数は再代入不可
catch (NullPointerException | ArithmeticException e) {
    e = new NullPointerException(); // コンパイルエラー
}

問題7 ⭐⭐⭐(チャレンジ)

次のコードをコンパイル・実行すると、どうなりますか?

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("try");
            throw new Exception();
        } catch (Exception e) {
            System.out.println("catch");
            return;
        } finally {
            System.out.println("finally");
        }
        System.out.println("after try-catch");
    }
}
  • A. trycatchfinallyafter try-catch
  • B. trycatchfinally
  • C. trycatchafter try-catch
  • D. コンパイルエラー
解答と解説

正解: D

tryブロックはthrow new Exception()で必ず例外をスローするため正常完了しません。catchブロックはreturn文があるため正常完了しません。JLS 14.21(到達可能性ルール)により、try-catch-finallyブロック全体が正常完了する可能性がないため、その後のSystem.out.println("after try-catch")は**到達不能コード(unreachable statement)**となりコンパイルエラーになります。

もしcatchブロック内のreturnを削除すれば、catchブロックが正常完了するようになり、出力は trycatchfinallyafter try-catch となります。

finallyブロックに関する重要なポイント:

  • finallyブロックはreturnがある場合でも、returnの前に実行される
  • ただし到達不能コードがあるとコンパイルエラーになる

問題8 ⭐⭐(応用)

次のコードをコンパイル・実行すると、どうなりますか?

public class MyResource implements AutoCloseable {
    String name;

    MyResource(String name) {
        this.name = name;
        System.out.println("Opening " + name);
    }

    @Override
    public void close() {
        System.out.println("Closing " + name);
    }

    public static void main(String[] args) {
        try (MyResource r1 = new MyResource("A");
             MyResource r2 = new MyResource("B")) {
            System.out.println("Using resources");
        }
    }
}
  • A. Opening AOpening BUsing resourcesClosing AClosing B
  • B. Opening AOpening BUsing resourcesClosing BClosing A
  • C. Opening AOpening BUsing resources
  • D. コンパイルエラー
解答と解説

正解: B

try-with-resourcesの重要なルール:

  • リソースは宣言された逆順close()される
  • r1(A)が先に開かれ、r2(B)が後に開かれる
  • クローズは逆順: r2(B)が先にクローズ → r1(A)が後にクローズ

出力:

Opening A
Opening B
Using resources
Closing B
Closing A

逆順でクローズするのは、後に開いたリソースが先に開いたリソースに依存している可能性があるためです。リソースクラスはAutoCloseable(またはCloseable)インターフェースを実装する必要があります。


問題9 ⭐⭐⭐(チャレンジ)

次のうち、例外クラスの継承階層として正しいものはどれですか?

  • A. ObjectThrowableExceptionRuntimeExceptionError
  • B. ObjectThrowableError / Exception(分岐)→ Exceptionの下にRuntimeException
  • C. ObjectExceptionThrowableRuntimeException
  • D. ObjectThrowableRuntimeExceptionException
解答と解説

正解: B

Javaの例外階層:

Object
 └── Throwable
      ├── Error(非検査、回復不能: OutOfMemoryError, StackOverflowError 等)
      └── Exception(検査例外)
           ├── IOException
           ├── SQLException
           └── RuntimeException(非検査例外)
                ├── NullPointerException
                ├── ArrayIndexOutOfBoundsException
                ├── ArithmeticException
                ├── ClassCastException
                └── IllegalArgumentException

重要な分類:

  • 検査例外: ExceptionのサブクラスのうちRuntimeException以外 → try-catchまたはthrowsが必須
  • 非検査例外: RuntimeExceptionとそのサブクラス → try-catch/throwsは任意
  • エラー: Errorとそのサブクラス → 通常はキャッチしない

問題10 ⭐⭐⭐(チャレンジ)

次のコードをコンパイル・実行すると、どうなりますか?

class ParentException extends Exception {}
class ChildException extends ParentException {}

public class Main {
    public static void main(String[] args) {
        try {
            throw new ChildException();
        } catch (ParentException e) {
            System.out.println("ParentException caught");
        } catch (ChildException e) {
            System.out.println("ChildException caught");
        }
    }
}
  • A. ParentException caught
  • B. ChildException caught
  • C. ParentException caughtChildException caught
  • D. コンパイルエラー
解答と解説

正解: D

catchブロックの順序に関するルールにより、コンパイルエラーになります。ChildExceptionParentExceptionのサブクラスなので、最初のcatch (ParentException e)ですべてのChildExceptionも捕捉されます。結果として2番目のcatch (ChildException e)には到達できず、コンパイラはこれを検出してエラーにします。

catchブロックはサブクラスを先に、スーパークラスを後に記述する必要があります。

正しい順序:

try {
    throw new ChildException();
} catch (ChildException e) {    // サブクラスが先
    System.out.println("ChildException caught");
} catch (ParentException e) {   // スーパークラスが後
    System.out.println("ParentException caught");
}

参考


@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?