DEV Community

TANIAOKA, Akihiro
TANIAOKA, Akihiro

Posted on

13章71

このJavaのコードに関する設問で、選択肢CとDが正しい理由を説明します。

まず、選択肢Cが「mainメソッドとsampleメソッドの両方にthrows Exceptionを追加する」と述べています。コードを見ると、sample メソッド内で Exception を投げる可能性があります(if (str == null) throw new Exception();)。しかし、この例外は sample メソッド内で捕捉(catch)されておらず、呼び出し元に伝播されます。つまり、main メソッドもこの例外を捕捉するか、または throws Exception を使用して呼び出し元に伝播させる必要があります。main メソッドがこの例外を捕捉しないため、throws Exception を追加する必要があります。

次に、選択肢Dです。これは「sampleメソッドの宣言にthrows Exceptionを追加し、catchブロックの型をExceptionに変更する」と説明しています。この変更が必要な理由は、sample メソッドが Exception を投げる可能性があるためです。現在の catch ブロックでは RuntimeException だけを捕捉しており、Exception は捕捉されません。これは、RuntimeExceptionException のサブクラスであるため、より広範な例外タイプを捕捉するために Exception を使用する必要があります。

これらの変更を加えることで、コードはすべての可能性のある例外を適切に処理できるようになります。選択肢CとDが正しい答えとされているのは、これらの理由に基づいています。

追記

選択肢CとDを適用した場合、Javaプログラムのコードは以下のように変更されます。

選択肢C: main メソッドと sample メソッドの両方に throws Exception を追加

この選択肢を適用すると、main メソッドと sample メソッドが Exception を投げる可能性があると宣言され、呼び出し元がこれを処理する責任を持つことになります。

public class Main {
    public static void main(String[] args) throws Exception {  // throws Exceptionを追加
        try {
            if (args.length == 0) {
                sample(null);
            } else {
                sample(args[0]);
            }
        } catch (RuntimeException e) {
            System.out.println("error");
        }
    }

    private static void sample(String str) throws Exception {  // throws Exceptionを追加
        if (str == null) throw new Exception();
        throw new RuntimeException();
    }
}
Enter fullscreen mode Exit fullscreen mode

選択肢D: sample メソッドの宣言に throws Exception を追加し、catch ブロックの型を Exception に変更する

この選択肢を適用すると、sample メソッドが Exception を投げることを宣言し、main メソッドの catch ブロックでより広範な Exception を捕捉します。

public class Main {
    public static void main(String[] args) {
        try {
            if (args.length == 0) {
                sample(null);
            } else {
                sample(args[0]);
            }
        } catch (Exception e) {  // RuntimeExceptionからExceptionへ変更
            System.out.println("error");
        }
    }

    private static void sample(String str) throws Exception {  // throws Exceptionを追加
        if (str == null) throw new Exception();
        throw new RuntimeException();
    }
}
Enter fullscreen mode Exit fullscreen mode

選択肢CとDのどちらもコードを正しくコンパイル可能にし、sample メソッドから投げられる ExceptionRuntimeException を適切に扱えるようにします。選択肢Dは、Exception による広範なエラー処理を可能にし、全ての例外タイプをキャッチできるようにしています。一方、選択肢Cはmain メソッドが例外を投げることを宣言していますが、これによりこのメソッドを呼び出すすべての上位メソッドも例外処理を行う必要が生じます。

補足

選択肢CとDが提案する解決策は類似していますが、それぞれ異なるアプローチを取っている点に注意が必要です。両選択肢の理解と使い分けについて説明します。

選択肢C

適用される変更: main メソッドと sample メソッドの両方に throws Exception を追加します。

目的: この変更により、sample メソッドから Exception が投げられる場合、その例外を main メソッドがキャッチしなくても良いようになります。代わりに、main メソッドも例外を呼び出し元に伝播させることが宣言されます。これにより、例外処理の責任が main メソッドの呼び出し元に移されます。

利用シナリオ: アプリケーション全体で例外処理のポリシーが統一されており、特定の例外が最上位まで伝播してから一括でキャッチされるべき場合や、例外処理の責任を明確に分離したい場合に適しています。

選択肢D

適用される変更: sample メソッドの宣言に throws Exception を追加し、main メソッド内の catch ブロックの例外タイプを RuntimeException から Exception に変更します。

目的: sample メソッドが Exception を投げる可能性があることを宣言し、main メソッド内の catch ブロックで Exception(及びそのすべてのサブクラス)をキャッチできるようにします。これにより、main メソッドで発生したすべての例外をローカルで処理し、プログラムの安定性を高めることができます。

利用シナリオ: メソッド内で発生したすべての例外をその場で処理し、エラーハンドリングをメソッド内にカプセル化したい場合に適しています。これは、プログラムの他の部分に影響を与えずにエラーを管理するために有用です。

CとDの違いと使い分け

  • 選択肢Cは例外の伝播を推進し、上位のメソッド(またはエントリポイントの外部)で一括して例外を処理する戦略です。このアプローチは、例外処理をアプリケーション全体で一元管理したい場合や、例外をさらに外部に伝えることが適切な場合に役立ちます。
  • 選択肢Dは、特定のメソッド内で完全に例外を処理することを目的としています。これにより、エラーハンドリングがそのメソッド内に閉じられ、他のメソッドの実行に影響を与えないようにします。これは、エラーの影響を局所化して処理する必要がある場合に有効です。

これらの違いを理解することで、プログラムの設計において適切なエラーハンドリング戦略を選択する際の判断材料とすることができます。

Top comments (0)