試してみたところマルチキャッチ私の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()
コンパイルされないのはなぜですか?
ベストアンサー1
表現の種類
b ? new Excep1() : new Excep2()
は です。これはとException
の共通スーパータイプだからです。Excep1
Excep2
ただし、 をキャッチしていないException
ため、コンパイラはそれについてエラーを出力します。
をキャッチするとException
、コンパイルが成功します。
public int m2(boolean b) {
try {
throw b ? new Excep1() : new Excep2();
} catch (Exception e) {
return 0;
}
}
あなたの例の条件付き三項式の種類を説明している JLS エントリを見つけようとしました。
私が見つけたのは、この特定の表現が15.25.3. 参照条件式。
これがポリ式としてカウントされるのか、スタンドアロン式としてカウントされるのか、よくわかりません。スタンドアロンだと思います (ポリ式には代入コンテキストまたは呼び出しコンテキストが関係しており、ステートメントはthrow
どちらにもカウントされないと思うため)。
スタンドアロン式の場合: 「2 番目と 3 番目のオペランドが同じ型 (null 型の場合もあります) の場合、それが条件式の型になります。」
あなたの場合、2 番目と 3 番目のオペランドには 、および という3 つの共通型がありObject
、式の型は後者の 2 つのいずれかである必要があります。これは、「throw ステートメント内の式は、型 Throwable に代入可能な (§5.2) 参照型の変数または値を示す必要がある」ためです。Throwable
Exception
コンパイラは最も具体的な共通型 ( Exception
) を選択し、その結果、catch (Exception e)
コンパイル エラーが解決されるようです。
また、2 つのカスタム例外を の 2 つのサブクラスに置き換えようとしましたがIOException
、その場合、catch (IOException e)
コンパイル エラーは解決されます。