次のように、引き続きジェネリック メソッドを使用できます。
public class SomeException {
private final Object target;
public SomeException(Object target) {
this.target = target;
}
public <T> T getTarget() {
return (T) target;
}
}
....
catch (SomeException e) {
Integer target = e.getTarget();
}
上記のクリスチャンの答えに同意します。受け入れられた回答は技術的には正しいですが (JVM 仕様を参照している限り)、Cristian Vasile の回答は、制限を満たし、さらには挑戦するものです。
この質問への回答で、私が同意せず反論する議論が少なくとも 2 つあります。これらの回答の引数が正しければ、これらの引数を使用して、現在正常に使用されている他のコンテキストでジェネリックを攻撃できます。
最初の引数は、これを使用できないことを示しています。
catch (Exception<T1> e) {}
JVM は の操作方法を認識していないためException<T1>
です。この引数は、JVM が使用方法を知らないことに基づいて、このジェネリックの使用も攻撃しているように見えますList<T1>
。
List<T1> list;
もちろん、引数は、コンパイラが型消去を実行することを忘れているため、JVM は を処理する方法を知る必要はありませんException<T1>
。Exception
を処理するのと同じように、単純に を処理できますList
。
もちろん、型消去のために同じ try/catch でcatch(Exception<T1> e)
andを処理することはできませんでしcatch(Exception<T2> e)
たが、それは今日のメソッド引数または戻り値よりも悪いことではありません:今日もmyMethod(List<T1>)
andを処理しませんmyMethod(List<T2>)
... (これを繰り返します)以下の 2 番目の反論の側面。)
2 番目の引数は次のようになります。これは許可されません:
catch (Exception<T1> e) {}
これはうまくいかないので:
catch (Exception<T1> e) {}
catch (Exception<T2> e) {}
では、これを禁止しない理由は次のとおりです。
interface MyInterface {
Comparable<Integer> getComparable();
}
これは機能しないため:
interface MyInterface {
Comparable<Integer> getComparable();
Comparable<String> getComparable();
}
またはこれ:
interface MyInterface {
void setComparable(Comparable<Integer> comparable);
}
これは機能しないため:
interface MyInterface {
void setComparable(Comparable<Integer> comparable);
void setComparable(Comparable<String> comparable);
}
言い換えれば、ほとんどの場合ジェネリックを禁止しないのはなぜでしょうか?
この 2 番目の引数は、これらのコンテキストで同じ非ジェネリック コンストラクトを消去するさまざまなジェネリック コンストラクトを許可することはできませんが、型が消去されない限り、次善の策を講じてジェネリックを許可できることを忘れています。同じタイプに。これがメソッド パラメーターで行うことです。ジェネリックの使用を許可しますが、型消去後に重複するシグネチャが検出されるとすぐに文句を言います。まあ、例外とキャッチブロックで同じことをすることもできたでしょう...
結論として、私はクリスチャンの答えを拡張します。一般的な例外クラスをcatch
許可し、ブロックで生の型を使用する代わりに:
class MyException<T> {}
...
catch (MyException e) { // raw
Java は問題なく実行できたはずです。
class MyException<T> {}
...
catch (MyException<Foo> e) {