Java-8で複数の例外をキャッチする


71

私の方法で見つけたマルチキャッチ機能を試している間、m1()すべてが期待どおりにうまく機能しています。

ただし、m2()同じコードではコンパイルされません。コードの行数を減らすために構文を変更しました。

public class Main {

    public int m1(boolean bool) {
        try {
            if (bool) {
                throw new Excep1();
            }
            throw new Excep2();
            //This m1() is compiling  abs fine.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    public int m2(boolean b) {
        try {
            throw b ? new Excep1() : new Excep2();
            //This one is not compiling.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    private static interface I {
    }

    private static class Excep1 extends Exception implements I {
    }

    private static class Excep2 extends Exception implements I {
    }
}

メソッドがm2()コンパイルされないのはなぜですか?


22
どのようなコンパイルエラーが発生していますか?
ギャビン

回答:


79

式のタイプ

b ? new Excep1() : new Excep2()

であるExceptionことが共通のスーパータイプだから、Excep1Excep2

ただし、をキャッチしていないExceptionので、コンパイラーはそれについて不平を言います。

をキャッチするとException、コンパイルに合格します。

public int m2(boolean b) {
    try {
        throw b ? new Excep1() : new Excep2();
    } catch (Exception e) {
        return 0;
    }
}

あなたの例で条件付き三項式のタイプを説明するJLSエントリを見つけようとしました。

この特定の式が15.25.3であることを見つけることができました。参照条件式

それがポリ式として計算されるのか、スタンドアロン式として計算されるのかは、完全にはわかりません。私はそれがスタンドアロンであると思います(poly式には代入コンテキストまたは呼び出しコンテキストが含まれるため、throwステートメントがこれらのどちらにも数えられないと思います)。

スタンドアロン式の場合:「2番目と3番目のオペランドが同じ型(null型の場合もある)である場合、それは条件式の型です。」

あなたのケースでは、第2および第3のオペランドは、3つの一般的な種類を持っている- ObjectThrowableおよびException- throwステートメントでの発現は、いずれかの参照型の変数または値を示す必要がある」、以来、式の型は、後者の二つのいずれかでなければなりませんこれはタイプThrowableに割り当て可能(5.2)です。」

コンパイラは最も具体的な一般的なタイプ(Exception)を選択しているように見えるため、a catch (Exception e)がコンパイルエラーを解決します。

また、2つのカスタム例外をの2つのサブクラスに置き換えようとしました。IOExceptionこの場合catch (IOException e)、コンパイルエラーが解決されます。


11
@Smile三項条件式のタイプは、第2オペランドと第3オペランドの両方に共通である必要があります。したがって、Excep1またはにすることはできませんExcep2。それだけですException
エラン

2
15.25.3の最後の箇条書きの答えは次のとおりです。「そうでない場合、2番目と3番目のオペランドはそれぞれタイプS1とS2です。T1をS1にボクシング変換を適用した結果のタイプとし、T2を結果のタイプとしますボクシング変換のS2への適用から。条件式のタイプは、キャプチャ変換(§5.1.10)をlub(T1、T2)に適用した結果です。ここのlubはLeast Upper Boundです。これは、2つの式のタイプが共有する最も近い共通のスーパータイプです。
アマロイ

22

コンパイラーを次の行と混同しています。

throw b ? new Excep1() : new Excep2();

コンパイラーは、式の結果(throwの左側)がExcept1とExcept2の間の共通のスーパークラスであるExceptionであることを認識しているため、スローする有効な型はExceptionになります。catchステートメントは、Excep1またはExcept2をスローしようとしていることを認識できません。


4

Javaは、メソッドがスローできるすべての例外タイプをキャッチまたは宣言することを制限します。

両方の(/ all)例外の共通の親を検索し、スローとしてキャッチまたは宣言することを期待します。たとえば、Excep1エクステンドの場合、スロー可能Throwableもキャッチする必要があります。

最初のケースでは、Javaはあなたが投げているかExcep1Excep2

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.