13

私は本当に理解できないものを構築しました - それがどのように機能するのかわかりません。このマルチキャッチの説明記事に慣れてきました。

次の 2 つの例外とコードを検討してください。

public class MyException1 extends Exception {
  // constructors, etc
  String getCustomValue();
}

public class MyException2 extends Exception {
  // constructors, etc
  String getCustomValue() { return "foo"; }
}

try {
  //...
} catch (MyException1|MyException2 e) {
  e.getCustomValue(); // won't work, as I expected
}

メソッドは同じですが、を呼び出すことはできませんgetCustomValue().Javaの内部では、上記try/catchは実際にMyException1/2to をキャストすることになっているためExceptionです(ドキュメントを理解した方法です)。

ただし、次のようなインターフェイスを導入すると:

public interface CustomValueGetter {
  String getCustomValue();
}

public class MyException1 extends Exception implements CustomValueGetter /*...*/
public class MyException2 extends Exception implements CustomValueGetter /*...*/

それを両方の例外に追加すると、Javaは実際にそのメソッドを使用できるようにします。そして、これを呼び出すことは有効です:

try {
  //...
} catch (MyException1|MyException2 e) {
  e.getCustomValue(); // does work
}

要するに、私の質問は次のとおりです。ここで実際に何が起こっているのか: (MyException1|MyException2 e).

とはe?

  • 最も近いスーパークラスが のタイプとして選択されていeますか? この質問はそれについて尋ねており、おそらくそれが答えです。もしそうなら、e にアクセスしたときに CustomValueGetter インターフェイスが「見える」のはなぜですか? 私の場合eException.

  • そうでない場合、実際のクラスがどちらかである場合、MyException1またはMyException2これらのクラスの両方で利用可能な同じメソッドを単に呼び出すことができないのはなぜですか?

  • e両方の例外のすべての共通インターフェースを実装し、最も近い共通スーパークラス型である、動的に生成されたクラスのインスタンスですか?

4

3 に答える 3

4

Ischuetze が言ったように、e は両方の例外が共有するクラスまたはインターフェイスを探しています。最初の例では、例外クラスにもかかわらず共有クラスが見つからないため、それによって提供されるメソッドしか使用できません。

例をこのコードに変更すると、再度コンパイルできるようになります。

public class MyException12 extends Exception {
    public String getCustomValue(){ return "boo"; };
}

public class MyException1 extends MyException12{
    public String getCustomValue() { return "foo"; };
}

public class MyException2 extends MyException12{
    // constructors, etc
    public String getCustomValue() { return "foo"; };
}

インターフェイスを使用した例のように、例外は、 と の両方が機能MyException1MyException2持っているMyException12ため、その機能を使用できることを通知します。

これは、問題全体に答えるSOの質問であり、eのタイプは何ですか。

回答のリンクからの引用:

例外タイプの処理を変更すると、2 つの方法でタイプ システムに影響します。すべてのタイプに対して実行される通常のタイプ チェックに加えて、例外タイプは追加のコンパイル時間分析を受けます。型チェックの目的で、論理和で宣言された catch パラメーターの型は lub(t1, t2, ...) (JLSv3 §15.12.2.7) であり、ti は catch 句が処理するように宣言されている例外の型です。非公式には、lub (最小上限) は、問題の型の最も具体的なスーパータイプです。マルチキャッチ例外パラメーターの場合、キャッチされたすべての例外の型は Throwable のサブクラスでなければならないため、問題の型の最小上限が常に存在します。したがって、Throwable は問題の型の上限であり、ただし、Throwable の一部のサブクラスが問題の型のスーパークラス (したがってスーパータイプでもある) である可能性があり、問題の例外型が共通のインターフェイスを実装している可能性があるため、これは最小の上限ではない可能性があります。(lub は、スーパークラスと 1 つまたは複数のインターフェイスの交差型にすることができます。) 例外チェック (JLSv3 §11.2) の目的で、最終または実質的に最終の catch パラメーターを再スローする throw ステートメント (JLSv3 §11.2.2) は、次のような例外タイプを正確にスローするものとして扱われます。

于 2015-08-27T06:25:19.927 に答える
4

最初のコード例では、Java は自動的に推論できず、その両方MyException1MyException2関数を実装していますgetCustomValuee両方の型階層における最大の共通分母も同様です。つまりException、機能を持っていませんgetCustomValue。したがって、機能していません。

Java は厳密に型指定されており、関数の名前が似ているにもかかわらず、同じ型で宣言されている場合と同じではありません。

2 番目のコードでは、両方の例外が実装されてCustomValueGetterいます。したがって、を実装eする最大公約数です。CustomValueGettergetCustomValue

于 2015-08-27T06:15:10.893 に答える