例外のcatchingやJavaジェネリックのシグネチャに関する予期しない問題が発生しました。さらに騒ぎがなければ、問題のコード(説明は以下の):一般的な引数を持つJavaメソッドcatchブロックの結果から呼び出される
public class StackOverflowTest {
private static class WrapperBuilder {
public static <T> ResultWrapper of(final T result) {
return new ResultWrapper<>(result);
}
public static ResultWrapper of(final RuntimeException exc) {
return new ResultWrapper<>(exc);
}
}
private static class ResultWrapper<T> {
private final T result;
private final RuntimeException exc;
ResultWrapper(final T result) {
this.result = result;
this.exc = null;
}
ResultWrapper(final RuntimeException exc) {
this.result = null;
this.exc = exc;
}
public Boolean hasException() {
return this.exc != null;
}
public T get() {
if (hasException()) {
throw exc;
}
return result;
}
}
private static class WrapperTransformer {
public ResultWrapper<Result> getResult(ResultWrapper originalWrappedResult) {
if (originalWrappedResult.hasException()) {
try {
originalWrappedResult.get();
} catch (Exception e) {
return WrapperBuilder.of(e);
}
}
return originalWrappedResult; // Transformation is a no-op, here
}
}
private static class Result {}
WrapperTransformer wrapper = new WrapperTransformer();
@Test
public void testBehaviour() {
ResultWrapper wrappedResult = WrapperBuilder.of(new RuntimeException());
final ResultWrapper<Result> result = wrapper.getResult(wrappedResult);
assertTrue(result.hasException()); // fails!
}
}
はともかくは、一瞬のために、悪いスタイルの質問(私は完全にを行うにはより良い方法があることを認めるが、私がやっている何をすべきか!下流のサービスへの呼び出しの結果をラップResultWrapper
- クラス:ここでは)、これは、次のビジネス・ロジックのトリムダウンと匿名のバージョンがあります。それのいずれかの呼び出し、または得られた例外
WrapperTransformer
が何らかの方法でResultWrapperを変換するための責任があるクラス(ただし、ここでは、「形質転換」は、何もしません)
試験の結果を含みます上記の失敗は失敗します。デバッグでは、WrapperBuilder.of(e)
が実際には汎用メソッド(つまりof(final T result)
)を呼び出しているため、これが原因であると判断しました。一般的な議論が "欲張り"であれば - RuntimeException
はで、T
であるので、その方法は賢明な(意図しない)選択である。しかし
、DownstreamWrapper::getResult
方法がに変更されます。
// i.e. explicitly catch RuntimeException, not Exception
} catch (RuntimeException e) {
return WrapperBuilder.of(e)
}
、テストが失敗した - Exception
がRuntimeException
として識別される。すなわち、非ジェネリック.of
メソッドが呼び出され、その結果ResultWrapper
が持っています人口はexc
です。
これは私にとって完全に難解です。 catch (Exception e)
句の中でさえ、e
は元のタイプを保持していると思います(ログメッセージSystem.out.println(e.getClass().getSimpleName()
はそうだと思います) - キャッチの "タイプ"を変更すると、ジェネリックメソッドのシグネチャがどのように変更されますか?
素晴らしいです、ありがとうございます! – scubbo