Java Gold SE11試験において「例外処理とアサーション」は、仕様の細かい理解が問われる得点源です。 特にtry-with-resourcesの実行順序や、アサーションの適切な利用シーンは引っかけ問題の常連。 本記事では、合格に必要な知識をギュッと凝縮して解説します。
- 例外の継承構造: Throwableを頂点とした階層を完璧に把握
- try-with-resources: リソースが閉じる「逆順」のルールを徹底解説
- アサーション: 公開メソッドでの利用がNGな理由とは?
- マルチキャッチ: 記述できる条件とコンパイルエラーのパターン
1. 例外の階層構造とチェック例外の判別
Java Goldでは、例外クラスの継承関係が頭に入っていないと解けない問題が頻出します。
- チェック例外(Exception直下): コンパイル時に処理が必須(IOExceptionなど)
- 非チェック例外(RuntimeException直下): 実行時に発生(NullPointerExceptionなど)
- エラー(Error直下): 回復不能な致命的状況(StackOverflowErrorなど)
2. try-with-resourcesの実行順序
Java SE 7から導入されたこの機能、試験では「いつ、どの順番でリソースが閉じられるか」が狙われます。
リソースは**宣言された順序の『逆順』**でクローズされるよ。もし複数の例外が発生した場合は、リソースクローズ時の例外は『抑制された例外』として扱われる点も要注意!」
3. アサーションの適切な使い方
アサーション(assert文)は、開発時のデバッグ用ツールです。試験では「使ってはいけない場面」を問う問題が必ず出ます。
- ◎ 適切な例: privateメソッドの引数チェック(内部的な論理確認)
- × 不適切な例: publicメソッドの引数チェック(通常の例外を投げるべき)
- × 不適切な例: 業務ロジック(状態を変化させる処理)を含めること
4. 試験に出る!例外・アサーション実戦例題
本番の試験形式に合わせたオリジナル例題です。正解だけでなく、なぜ他が間違っているのか(解説)が合格への近道になります。
【例題1】try-with-resourcesの実行順
次のコードを実行したとき、コンソールに表示される順序として正しいものはどれですか?
Java
class MyResource implements AutoCloseable {
String name;
MyResource(String name) { this.name = name; }
public void close() { System.out.print(name + " "); }
}
public class Main {
public static void main(String[] args) {
try (MyResource r1 = new MyResource("A");
MyResource r2 = new MyResource("B")) {
System.out.print("Body ");
}
}
}
A. Body A B B. Body B A C. A B Body D. B A Body
【解説】
正解:B try-with-resourcesにおいて、リソースは**「宣言された順序の逆順」**でクローズされます。
最初に宣言された r1 がクローズされる(A) この順序(Body → B → A)は、試験で最も狙われるポイントの一つです。
tryブロック内の処理が実行される(Body)
最後に宣言された r2 がクローズされる(B)
【例題2】アサーションの適切な利用
アサーションの使用方法として、適切なものはどれですか?(2つ選択)
A. 公開(public)メソッドの引数が有効範囲内かチェックするために使用する。
B. 非公開(private)メソッドの引数が、想定通りの値であるか確認するために使用する。
C. assert (x = 10) > 0; のように、変数の値を更新する処理を含めて記述する。
D. 条件分岐(switch文)の default ラベルなど、「絶対に到達しないはずの場所」に到達していないか確認するために使用する。
【解説】
正解:B, D アサーションはあくまで「開発者の想定(論理)」を確認するためのものです。
Cがダメな理由: アサーションは実行時に無効化(-da)される可能性があるため、その中で変数の値を書き換える(副作用のある)処理を書いてはいけません。
Aがダメな理由: publicメソッドの引数チェックは、アサーションではなく通常の例外(IllegalArgumentException等)を投げるのがルールです。
【例題3】例外のキャッチ順序
次のコードをコンパイルした際、結果として正しいものはどれですか?
Java
try {
throw new java.io.IOException();
} catch (Exception e) {
System.out.println("Exception");
} catch (java.io.IOException e) {
System.out.println("IOException");
}
A. 「Exception」と表示される B. 「IOException」と表示される C. コンパイルエラーが発生する D. 実行時に例外がスローされる
【解説】
正解:C 例外をキャッチする際は、「サブクラス(具体的な例外)」から先に記述しなければなりません。 このコードでは、IOExceptionの親クラスである Exception が先に記述されているため、後の catch ブロックが「到達不能(Unreachable code)」となり、コンパイルエラーになります。
【例題4】例外の伝播とfinally
次のコードを実行したときの結果として、正しいものはどれですか?
Java
public class Main {
public static void main(String[] args) {
try {
method();
} catch (RuntimeException e) {
System.out.print("A ");
} finally {
System.out.print("B ");
}
}
static void method() {
throw new Error();
}
}
A. A B
B. B のみ表示され、その後スタックトレースが表示される
C. B A
D. コンパイルエラーになる
【解説】
正解:B ErrorはRuntimeExceptionを継承していないため、catchブロックでは捕捉されません。しかし、finallyは例外がキャッチされるかどうかに関わらず必ず実行されるため、Bが表示された後に異常終了します。
【例題5】マルチキャッチの制約
次のマルチキャッチの記述のうち、コンパイルエラーになるものはどれですか?
A. catch (IOException | SQLException e)
B. catch (ArithmeticException | NullPointerException e)
C. catch (FileNotFoundException | IOException e)
D. catch (RuntimeException | Error e)
【解説】
正解:C マルチキャッチでは、「継承関係(親子関係)にある例外を並べて記述すること」はできません。 IOExceptionはFileNotFoundExceptionの親クラスであるため、ルール違反となりコンパイルエラーになります。
【例題6】アサーションの有効化
アサーションを実行時に有効にするためのコマンドライン引数はどれですか?
A. -ea
B. -da
C. -assertion
D. -debug
【解説】
正解:A enableassertionsの略である -ea オプションを使用します。デフォルト(指定なし)や -da (disable)ではアサーションは実行されません。
【例題7】try-with-resourcesの条件
try-with-resourcesの括弧内で宣言するリソースが、必ず実装していなければならないインターフェースはどれですか?
A. java.io.Serializable
B. java.lang.AutoCloseable
C. java.lang.Runnable
D. java.util.stream.Stream
【解説】
正解:B リソースとして扱うためには、close()メソッドを定義した java.lang.AutoCloseable(またはそのサブの Closeable)を実装している必要があります。
【例題8】アサーション内での代入
次のコードの説明として正しいものはどれですか? assert x > 0 : x = -1;
A. xが0以下の場合、xに-1を代入して処理を続行する
B. アサーション失敗時にAssertionErrorが投げられ、詳細メッセージに更新後のxの値が含まれる
C. 第2引数で代入操作を行っているため、コンパイルエラーになる
D. このアサーションは常に有効であり、無効にできない
【解説】
正解:B 第2引数(コロンの後ろ)は値を返す式であれば代入式も許容されますが、アサーションが無効化されると実行されません。プログラムの主処理に影響を与える「副作用」のあるコードを書くのは不適切な設計とされます。
【例題9】抑制された例外(Suppressed Exception)
try-with-resourcesにおいて、tryブロックとcloseメソッドの両方で例外が発生した場合、close側の例外はどう扱われますか?
A. tryブロックの例外を上書きしてスローされる
B. 「抑制された例外」として、メインの例外に付加される
C. 無視され、破棄される
D. 両方をまとめたMultiExceptionがスローされる
【解説】
正解:B tryブロックの例外が「メイン」となり、close時の例外はそれにぶら下がる Suppressed Exception(抑制された例外) となります。Throwable.getSuppressed() で取得可能です。
【例題10】基本の実行順序
次のコードの出力結果は何ですか?
Java
try {
System.out.print("A ");
throw new RuntimeException();
} catch (Exception e) {
System.out.print("B ");
} finally {
System.out.print("C ");
}
A. A B C
B. A C
C. A B
D. B C
【解説】 正解:A
【解説】
正解:A
try内の処理実行(A) 2. 例外発生 3. 対応するcatch実行(B) 4. 最後にfinally実行(C) の順で全て出力されます。
まとめ:例外とアサーションを得点源にする
例外処理は、継承図と基本ルールさえ押さえれば確実に加点できるセクションです。特にアサーションは「-ea」オプションの有無など、基本的な実行仕様も忘れずに確認しておきましょう。


コメント