Java Silver 例外処理 問題

ゆめさくが作った練習問題です。本試験の問題ではありません。

例外処理の問題を1⁠4問、小分野ごとにまとめました。選ぶと、その場で正誤と解説が出ます。

ログインなしで解けます。答えはこのブラウザの中だけに残り、どこにも送りません。

この分野の小分野

  • 例外の種類と try-⁠catch(7問)
  • try-⁠with-⁠resources、カスタム例外、multi-⁠catch(7問)

例外処理の問題

14 問

選ぶと、すぐに正誤と解説が出ます。選んだ答えは変えられません。

  1. 例外の種類と try-catch

    問 1Throwable、Error、Exception、RuntimeException の継承の関係として正しいものはどれですか。

  2. 問 2次のコードをコンパイルしたときの結果として正しいものはどれですか。

    import java.io.IOException;
    
    public class Main {
        static void read() throws IOException {
            throw new IOException("x");
        }
        static void a() throws Exception {
            read();                              // (A)
        }
        static void b() {
            try {
                read();                          // (B)
            } catch (RuntimeException e) {
                System.out.print("R");
            }
        }
        static void c() {
            try {
                read();                          // (C)
            } catch (Exception e) {
                System.out.print("E");
            }
        }
        public static void main(String[] args) {
            c();
        }
    }
  3. 問 3次のコードをコンパイルしたときの結果として正しいものはどれですか。

    public class Main {
        public static void main(String[] args) {
            try {
                System.out.println("A");
            } catch (Exception e) {              // (A)
            }
            try {
                System.out.println("B");
            } catch (RuntimeException e) {       // (B)
            }
            try {
                System.out.println("C");
            } catch (java.io.IOException e) {    // (C)
            }
            try {
                System.out.println("D");
            } catch (Throwable e) {              // (D)
            }
        }
    }
  4. 問 4次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    public class Main {
        public static void main(String[] args) {
            try {
                try {
                    System.out.print("1");
                    throw new IllegalStateException();
                } catch (IllegalStateException e) {
                    System.out.print("2");
                    throw new IllegalArgumentException();
                } catch (IllegalArgumentException e) {
                    System.out.print("3");
                } finally {
                    System.out.print("4");
                }
            } catch (RuntimeException e) {
                System.out.print("5");
            }
            System.out.print("6");
        }
    }
  5. 問 5次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    public class Main {
        static int f() {
            try {
                System.out.print("T");
                throw new IllegalStateException();
            } finally {
                System.out.print("F");
                return 5;
            }
        }
        public static void main(String[] args) {
            try {
                System.out.print(f());
            } catch (IllegalStateException e) {
                System.out.print("E");
            }
        }
    }
  6. 問 6次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    public class Main {
        static StringBuilder f() {
            StringBuilder sb = new StringBuilder("T");
            try {
                return sb;
            } finally {
                sb.append("F");
                sb = new StringBuilder("X");
            }
        }
        public static void main(String[] args) {
            System.out.println(f());
        }
    }
  7. 問 7次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    public class Main {
        static void c() {
            System.out.print("c ");
            int[] a = new int[1];
            a[1] = 5;
            System.out.print("c2 ");
        }
        static void b() {
            try {
                c();
                System.out.print("b ");
            } finally {
                System.out.print("bF ");
            }
        }
        public static void main(String[] args) {
            try {
                b();
            } catch (IllegalArgumentException e) {
                System.out.print("M ");
            }
            System.out.print("end");
        }
    }
  8. try-with-resources、カスタム例外、multi-catch

    問 8次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    class Res implements AutoCloseable {
        private final String name;
        Res(String name) {
            if (name.equals("B")) {
                throw new IllegalStateException("B");
            }
            this.name = name;
            System.out.print("open" + name + " ");
        }
        @Override
        public void close() {
            System.out.print("close" + name + " ");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            try (Res a = new Res("A"); Res b = new Res("B"); Res c = new Res("C")) {
                System.out.print("body ");
            } catch (IllegalStateException e) {
                System.out.print("catch" + e.getMessage());
            }
        }
    }
  9. 問 9次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    class Res implements AutoCloseable {
        @Override
        public void close() {
            System.out.print("C ");
            throw new IllegalStateException("close");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            try (Res r = new Res()) {
                System.out.print("T ");
            } catch (IllegalStateException e) {
                System.out.print(e.getMessage() + " ");
            } finally {
                System.out.print("F");
            }
        }
    }
  10. 問 10次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    class Res implements AutoCloseable {
        private final String name;
        Res(String name) {
            this.name = name;
        }
        @Override
        public void close() {
            throw new IllegalStateException("close" + name);
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            try (Res a = new Res("A"); Res b = new Res("B")) {
                throw new RuntimeException("body");
            } catch (RuntimeException e) {
                System.out.print(e.getMessage());
                for (Throwable s : e.getSuppressed()) {
                    System.out.print(" " + s.getMessage());
                }
            }
        }
    }
  11. 問 11java.lang.AutoCloseable と java.io.Closeable の説明として正しいものはどれですか。

  12. 問 12次のコードをコンパイルしたときの結果として正しいものはどれですか。

    class Res implements AutoCloseable {
        private final String name;
        Res(String name) {
            this.name = name;
        }
        @Override
        public void close() {
            System.out.print("close" + name + " ");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Res r1 = new Res("1");
            Res r2 = new Res("2");
            r2 = new Res("3");                    // (A)
            try (r1; r2) {                        // (B)
                System.out.print("body ");
            }
        }
    }
  13. 問 13次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    class AppException extends Exception {
        AppException(String message, Throwable cause) {
            super(message, cause);
        }
    }
    
    public class Main {
        static void load() throws AppException {
            try {
                Integer.parseInt("x");
            } catch (NumberFormatException e) {
                throw new AppException("load", e);
            }
        }
        public static void main(String[] args) {
            try {
                load();
            } catch (AppException e) {
                System.out.print(e.getMessage() + " " + e.getCause().getClass().getSimpleName());
            }
        }
    }
  14. 問 14次のコードをコンパイルしたときの結果として正しいものはどれですか。

    public class Main {
        public static void main(String[] args) {
            try {
                if (args.length == 0) {
                    throw new IllegalStateException("s");
                }
                Integer.parseInt(args[0]);
            } catch (NumberFormatException | IllegalStateException e) {   // (A)
                System.out.print(e.getMessage());
                e = new IllegalStateException("t");                        // (B)
            }
        }
    }

14 問中 0 問に答えました

解説の一覧

解いたあとに読み返せるよう、全問の解説を並べています。問いを開くと解説が出ます。

例外の種類と try-⁠catch

問1Throwable、Error、Exception、RuntimeException の継承の関係として正しいものはどれですか。

正解は「Error と Exception が Throwable を継承し、RuntimeException が Exception を継承する」です。例外を表すクラスの根は Throwable で、その直接のサブクラスが Exception と Error です。RuntimeException は Exception の直接のサブクラスです。Error は回復を期待しない重大な問題を表し、Exception とは別の枝にあります。そのため catch (Exception e) と書いても Error は捕まりません。チェック例外かどうかもこの関係で決まり、RuntimeException とそのサブクラス、Error とそのサブクラスが非チェック例外、それ以外の Throwable の仲間がチェック例外です。ほかの 3 つは、RuntimeException を Throwable の直接の子にしたり、Error を Exception の下や上に置いたりしていて、どれも実際の関係と違います。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠1.html#jls-⁠1⁠1.1.1

問2次のコードをコンパイルしたときの結果として正しいものはどれですか。
import java.io.IOException;

public class Main {
    static void read() throws IOException {
        throw new IOException("x");
    }
    static void a() throws Exception {
        read();                              // (A)
    }
    static void b() {
        try {
            read();                          // (B)
        } catch (RuntimeException e) {
            System.out.print("R");
        }
    }
    static void c() {
        try {
            read();                          // (C)
        } catch (Exception e) {
            System.out.print("E");
        }
    }
    public static void main(String[] args) {
        c();
    }
}

正解は「(B) の行でコンパイルエラーになる」です。IOException はチェック例外です。チェック例外を投げうるメソッドを呼ぶときは、catch で捕まえるか、自分の throws にその例外か上位の型を書かなければコンパイルエラーになります。(A) の a は throws Exception と書いていて、Exception は IOException の上位の型なので問題ありません。(C) の c は catch (Exception e) で IOException も捕まえられるので問題ありません。(B) の b は catch (RuntimeException e) しか書いていませんが、IOException は RuntimeException のサブクラスではないので捕まえられず、throws もありません。そのため (B) で「報告されない例外 IOException」のエラーになります。コンパイルが通らないので「E と出力される」にもなりません。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠1.html#jls-⁠1⁠1.2.3

問3次のコードをコンパイルしたときの結果として正しいものはどれですか。
public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("A");
        } catch (Exception e) {              // (A)
        }
        try {
            System.out.println("B");
        } catch (RuntimeException e) {       // (B)
        }
        try {
            System.out.println("C");
        } catch (java.io.IOException e) {    // (C)
        }
        try {
            System.out.println("D");
        } catch (Throwable e) {              // (D)
        }
    }
}

正解は「(C) の行でコンパイルエラーになる」です。catch にチェック例外の型を書くとき、対応する try ブロックがその例外 (またはそのサブクラスかスーパークラス) を投げうるものでなければコンパイルエラーになります。System.out.println は IOException を投げると宣言していないので、(C) の catch (java.io.IOException e) は「この try の中では投げられない例外を捕まえている」というエラーです。ただし Exception と Throwable はこの決まりの対象外で、try の中身にかかわらず書けます。この 2 つは非チェック例外も捕まえうるからです。そのため (A) と (D) は問題ありません。(B) の RuntimeException は非チェック例外なので、try の中身にかかわらずいつでも書けます。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠1.html#jls-⁠1⁠1.2.3

問4次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
public class Main {
    public static void main(String[] args) {
        try {
            try {
                System.out.print("1");
                throw new IllegalStateException();
            } catch (IllegalStateException e) {
                System.out.print("2");
                throw new IllegalArgumentException();
            } catch (IllegalArgumentException e) {
                System.out.print("3");
            } finally {
                System.out.print("4");
            }
        } catch (RuntimeException e) {
            System.out.print("5");
        }
        System.out.print("6");
    }
}

正解は「1⁠2⁠4⁠5⁠6」です。catch ブロックの中で例外が投げられると、その catch ブロックは途中で終わります。このとき同じ try 文の後ろの catch は調べられず、finally を実行したあと、try 文全体がその例外で終わって外側へ伝わります。内側の try で 1 を出力して IllegalStateException が投げられ、最初の catch で 2 を出力します。そこで IllegalArgumentException を投げても、すぐ後ろの catch (IllegalArgumentException e) には届きません。finally の 4 を出力したあと例外は外側の try に伝わり、catch (RuntimeException e) で捕まって 5 を出力し、最後に 6 を出力して「1⁠2⁠4⁠5⁠6」です。「1⁠2⁠3⁠4⁠6」と「1⁠2⁠3⁠4」は同じ try の後ろの catch が捕まえると考えた結果、「1⁠2⁠4 と出力されたあと例外で止まる」は外側の catch を見落とした結果です。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠4.html#jls-⁠1⁠4.2⁠0.2

問5次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
public class Main {
    static int f() {
        try {
            System.out.print("T");
            throw new IllegalStateException();
        } finally {
            System.out.print("F");
            return 5;
        }
    }
    public static void main(String[] args) {
        try {
            System.out.print(f());
        } catch (IllegalStateException e) {
            System.out.print("E");
        }
    }
}

正解は「TF5」です。finally ブロックは、try ブロックが例外で終わっても必ず実行されます。そして finally ブロックが return などで途中で終わると、try 文全体がその理由で終わり、try で投げられた例外は捨てられます。f では T を出力したあと IllegalStateException が投げられ、finally で F を出力して return 5 を実行します。この return によって例外は消え、f は普通に 5 を返します。main では 5 が出力され、例外は届かないので catch は動かず、結果は「TF5」です。「TFE」は例外がそのまま呼び出し元に伝わると考えた結果です。「TF5E」は値が返ったうえで例外も伝わると考えた結果です。finally の中の return は文法上正しいので「コンパイルエラーになる」も誤りです。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠4.html#jls-⁠1⁠4.2⁠0.2

問6次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
public class Main {
    static StringBuilder f() {
        StringBuilder sb = new StringBuilder("T");
        try {
            return sb;
        } finally {
            sb.append("F");
            sb = new StringBuilder("X");
        }
    }
    public static void main(String[] args) {
        System.out.println(f());
    }
}

正解は「TF」です。return 文は、まず式を評価して値を決め、それから finally を実行します。戻り値として決まるのは、return の時点で sb に入っていた値、つまり StringBuilder のオブジェクトを指す参照です。finally の sb.append("F") は、その同じオブジェクトの中身を書き換えるので、戻り値のオブジェクトも T から TF に変わります。一方 sb = new StringBuilder("X") は変数 sb に別のオブジェクトを入れるだけで、すでに決まった戻り値は変わりません。結果は「TF」です。「T」は基本型のときと同じように中身も変わらないと考えた結果です。「X」と「XF」は finally での代入が戻り値を置き換えると考えた結果です。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠4.html#jls-⁠1⁠4.1⁠7

問7次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
public class Main {
    static void c() {
        System.out.print("c ");
        int[] a = new int[1];
        a[1] = 5;
        System.out.print("c2 ");
    }
    static void b() {
        try {
            c();
            System.out.print("b ");
        } finally {
            System.out.print("bF ");
        }
    }
    public static void main(String[] args) {
        try {
            b();
        } catch (IllegalArgumentException e) {
            System.out.print("M ");
        }
        System.out.print("end");
    }
}

正解は「c bF と出力されたあと例外で止まる」です。例外が投げられると、制御はその場所を動的に囲んでいる最も近い、型の合う catch に移ります。捕まらなければ呼び出し元へ伝わり、main からも出るとプログラムが止まります。c では c を出力したあと、長さ 1 の配列の a[1] に書こうとして ArrayIndexOutOfBoundsException が投げられ、c2 は出力されません。b には catch が無いので b の残りも飛ばされますが、finally の bF は出力されます。main の catch は IllegalArgumentException だけを捕まえ、ArrayIndexOutOfBoundsException はそのサブクラスではないので捕まえられません。end も実行されず、結果は「c bF と出力されたあと例外で止まる」です。「c bF M end」は型の合わない catch でも捕まると考え、「c bF end」は捕まらなくても続きが動くと考え、「c と出力されたあと例外で止まる」は finally が動かないと考えた結果です。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠1.html#jls-⁠1⁠1.3

try-⁠with-⁠resources、カスタム例外、multi-⁠catch

問8次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
class Res implements AutoCloseable {
    private final String name;
    Res(String name) {
        if (name.equals("B")) {
            throw new IllegalStateException("B");
        }
        this.name = name;
        System.out.print("open" + name + " ");
    }
    @Override
    public void close() {
        System.out.print("close" + name + " ");
    }
}

public class Main {
    public static void main(String[] args) {
        try (Res a = new Res("A"); Res b = new Res("B"); Res c = new Res("C")) {
            System.out.print("body ");
        } catch (IllegalStateException e) {
            System.out.print("catch" + e.getMessage());
        }
    }
}

正解は「openA closeA catchB」です。try-⁠with-⁠resources のリソースは左から順に初期化されます。途中のリソースの初期化で例外が出ると、それまでに初期化できたリソースだけが逆の順に閉じられ、try ブロックは実行されません。まず a が作られて openA を出力します。次の b のコンストラクタで IllegalStateException が投げられるので b は作られず、c も作られません。初期化できたのは a だけなので closeA を出力し、そのあと catch で catchB を出力します。結果は「openA closeA catchB」です。「openA catchB」は作れたリソースも閉じられないと考えた結果、「openA closeA closeB catchB」は作れなかった b も閉じると考えた結果です。「openA catchB closeA」は catch のあとに閉じると考えた結果で、閉じるのは catch より前です。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠4.html#jls-⁠1⁠4.2⁠0.3

問9次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
class Res implements AutoCloseable {
    @Override
    public void close() {
        System.out.print("C ");
        throw new IllegalStateException("close");
    }
}

public class Main {
    public static void main(String[] args) {
        try (Res r = new Res()) {
            System.out.print("T ");
        } catch (IllegalStateException e) {
            System.out.print(e.getMessage() + " ");
        } finally {
            System.out.print("F");
        }
    }
}

正解は「T C close F」です。catch や finally の付いた try-⁠with-⁠resources は、リソースを使う部分を内側の try に置き、その外側に catch と finally を付けたものと同じ意味です。そのため、リソースは try ブロックのすぐあと、catch と finally より前に閉じられ、close で出た例外も外側の catch で捕まえられます。まず T を出力し、次に close で C を出力して IllegalStateException が投げられます。それを catch が捕まえて close を出力し、最後に finally の F を出力します。結果は「T C close F」です。「T F C」は finally のあとに閉じると考えた結果です。「T C F」は close の例外が無視されると考えた結果です。「T close C F」は catch が close より先に動くと考えた結果です。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠4.html#jls-⁠1⁠4.2⁠0.3.2

問10次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
class Res implements AutoCloseable {
    private final String name;
    Res(String name) {
        this.name = name;
    }
    @Override
    public void close() {
        throw new IllegalStateException("close" + name);
    }
}

public class Main {
    public static void main(String[] args) {
        try (Res a = new Res("A"); Res b = new Res("B")) {
            throw new RuntimeException("body");
        } catch (RuntimeException e) {
            System.out.print(e.getMessage());
            for (Throwable s : e.getSuppressed()) {
                System.out.print(" " + s.getMessage());
            }
        }
    }
}

正解は「body closeB closeA」です。try ブロックで例外が出たあと、リソースを閉じるときにも例外が出ると、close の例外は捨てられず、try ブロックの例外に「抑制された例外」として付け加えられます。catch に届くのは最初に出た try ブロックの例外で、抑制された例外は getSuppressed で配列として取り出せます。try ブロックで body の例外が出たあと、リソースは逆の順に b、a と閉じられ、closeB、closeA の例外がこの順に body の例外に付け加えられます。そのため body を出力したあと closeB、closeA の順に出力し、結果は「body closeB closeA」です。「closeA」は最後に出た例外が catch に届くと考えた結果です。「body closeA closeB」は閉じる順を宣言の順と考えた結果、「body」は close の例外が捨てられると考えた結果です。 出典 https://docs.oracle.com/en/java/javase/1⁠7/docs/api/java.base/java/lang/Throwable.html#getSuppressed()

問11java.lang.AutoCloseable と java.io.Closeable の説明として正しいものはどれですか。

正解は「Closeable は AutoCloseable を継承し、close は IOException を投げると宣言されている」です。java.io.Closeable は java.lang.AutoCloseable を継承したインタフェースです。AutoCloseable の close は throws Exception、Closeable の close は throws IOException と宣言されています。try-⁠with-⁠resources に書けるのは AutoCloseable を実装した型なので、Closeable を実装した型もそのまま使えます。「AutoCloseable は Closeable を継承し」は継承の向きが逆です。「例外を投げないと宣言」は close の宣言と違います。「Closeable だけが使える」は try-⁠with-⁠resources の条件と違います。 出典 https://docs.oracle.com/en/java/javase/1⁠7/docs/api/java.base/java/io/Closeable.html

問12次のコードをコンパイルしたときの結果として正しいものはどれですか。
class Res implements AutoCloseable {
    private final String name;
    Res(String name) {
        this.name = name;
    }
    @Override
    public void close() {
        System.out.print("close" + name + " ");
    }
}

public class Main {
    public static void main(String[] args) {
        Res r1 = new Res("1");
        Res r2 = new Res("2");
        r2 = new Res("3");                    // (A)
        try (r1; r2) {                        // (B)
            System.out.print("body ");
        }
    }
}

正解は「(B) の行でコンパイルエラーになる」です。try-⁠with-⁠resources の丸括弧には、新しい変数の宣言のほか、try の外で宣言した変数をそのまま書けます。ただしその変数は final か、実質的に final (初期化のあと一度も代入されていない) でなければなりません。r1 は初期化のあと代入されていないので実質的に final で、書いて問題ありません。r2 は (A) で代入し直しているので実質的に final ではなく、(B) の try (r1; r2) で「リソースとして使う変数が final でも実質的に final でもない」というエラーになります。(A) の代入そのものは普通の変数への代入なので、それだけではエラーになりません。コンパイルが通らないので、出力を答える 2 つの選択肢も誤りです。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠4.html#jls-⁠1⁠4.2⁠0.3

問13次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
class AppException extends Exception {
    AppException(String message, Throwable cause) {
        super(message, cause);
    }
}

public class Main {
    static void load() throws AppException {
        try {
            Integer.parseInt("x");
        } catch (NumberFormatException e) {
            throw new AppException("load", e);
        }
    }
    public static void main(String[] args) {
        try {
            load();
        } catch (AppException e) {
            System.out.print(e.getMessage() + " " + e.getCause().getClass().getSimpleName());
        }
    }
}

正解は「load NumberFormatException」です。Throwable には詳細メッセージと原因 (cause) を受け取るコンストラクタがあり、渡したメッセージは getMessage で、原因は getCause で取り出せます。自作の例外でも super(message, cause) と書けばこの仕組みをそのまま使えます。load では Integer.parseInt("x") が NumberFormatException を投げ、catch でそれを原因として AppException に包んで投げ直します。main では getMessage が load、getCause が元の NumberFormatException を返すので「load NumberFormatException」です。「load null」は原因が保存されないと考え、「load AppException」は getCause が自分を返すと考えた結果です。「コンパイルエラーになる」は自作の例外に引数付きのコンストラクタを書けないと考えた答えです。 出典 https://docs.oracle.com/en/java/javase/1⁠7/docs/api/java.base/java/lang/Throwable.html#getCause()

問14次のコードをコンパイルしたときの結果として正しいものはどれですか。
public class Main {
    public static void main(String[] args) {
        try {
            if (args.length == 0) {
                throw new IllegalStateException("s");
            }
            Integer.parseInt(args[0]);
        } catch (NumberFormatException | IllegalStateException e) {   // (A)
            System.out.print(e.getMessage());
            e = new IllegalStateException("t");                        // (B)
        }
    }
}

正解は「(B) の行でコンパイルエラーになる」です。multi-⁠catch の変数は、final と書かなくても暗黙に final になります。そのため catch の中で e に代入すると、(B) で「multi-⁠catch の変数 e には代入できない」というエラーになります。一方、multi-⁠catch に並べる型どうしが継承の関係にあるとコンパイルエラーですが、NumberFormatException は IllegalArgumentException のサブクラスで、IllegalStateException とは継承の関係が無いので、(A) は問題ありません。「(A) の行で」と「(A) と (B) の行で」は 2 つの型が親子だと考えた答えです。「s と出力される」は、1 つの型だけを書く catch の変数と同じように代入できると考えた答えで、実際にはコンパイルが通りません。 出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠4.html#jls-⁠1⁠4.2⁠0

ほかの分野

Java Silverの頁に、6分野の入口と試験の案内があります。

続きはゆめさくで

試験の知識を仕事につなげる一歩を、ここにまとめています。