33

チェック例外と実行時例外の両方をスローする可能性のあるコードがいくつかあります。

チェックされた例外をキャッチし、ランタイム例外でラップしたいと思います。ただし、RuntimeException がスローされた場合は、既にランタイム例外であるため、ラップする必要はありません。

私が持っているソリューションには少しオーバーヘッドがあり、「きれい」ではありません。

try {
  // some code that can throw both checked and runtime exception
} catch (RuntimeException e) {
  throw e;
} catch (Exception e) {
  throw new RuntimeException(e);
}

よりエレガントな方法のアイデアはありますか?

4

8 に答える 8

33

「ブラインド」再スローを使用して、チェック済みの例外を渡します。これを使用して、チェック済み例外をスローするラムダを使用できない Streams API を通過させました。たとえば、ThrowingXxxxx 機能インターフェイスがあるため、チェック済みの例外を渡すことができます。

これにより、呼び出し先がチェック例外を許可しないインターフェイスを介して渡す必要があることを知る必要なく、呼び出し元でチェック例外を自然にキャッチできます。

try {
  // some code that can throw both checked and runtime exception

} catch (Exception e) {
  throw rethrow(e);
}

呼び出し元のメソッドで、チェック済み例外を再度宣言できます。

public void loadFile(String file) throws IOException {
   // call method with rethrow
}

/**
 * Cast a CheckedException as an unchecked one.
 *
 * @param throwable to cast
 * @param <T>       the type of the Throwable
 * @return this method will never return a Throwable instance, it will just throw it.
 * @throws T the throwable as an unchecked throwable
 */
@SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
    throw (T) throwable; // rely on vacuous cast
}

例外を処理するためのさまざまなオプションが多数あります。それらのいくつかを使用します。

https://vanilla-java.github.io/2016/06/21/Reviewing-Exception-Handling.html

于 2016-09-27T08:11:54.500 に答える
19

グアバThrowables.propagate()はまさにこれを行います:

try {
    // some code that can throw both checked and runtime exception
} catch (Exception e) {
    throw Throwables.propagate(e);
}

更新: このメソッドは非推奨になりました。詳しい説明はこちらのページをご覧ください。

于 2016-09-27T08:33:29.537 に答える
4

あまり。

これを頻繁に行う場合は、ヘルパー メソッドに入れることができます。

static RuntimeException unchecked(Throwable t){
    if (t instanceof RuntimeException){
      return (RuntimeException) t;
    } else if (t instanceof Error) { // if you don't want to wrap those
      throw (Error) t;
    } else {
      return new RuntimeException(t);
    }
}

try{
 // ..
}
catch (Exception e){
   throw unchecked(e);
}
于 2016-09-27T08:10:14.923 に答える
2

以下を含む特別にコンパイルされた .class ファイルがあります。

public class Thrower {
    public static void Throw(java.lang.Throwable t) {
        throw t;
    }
}

それだけで機能します。通常、Java コンパイラはこれをコンパイルすることを拒否しますが、バイトコード検証ツールはまったく気にしません。

クラスは、Peter Lawrey の回答と同様に使用されます。

try {
  // some code that can throw both checked and runtime exception

} catch (Exception e) {
    Thrower.Throw(e);
}
于 2016-09-27T15:46:24.723 に答える
1

問題は、それExceptionが広すぎることです。可能なチェック例外が何であるかを正確に知っておく必要があります。

try {
    // code that throws checked and unchecked exceptions
} catch (IOException | SomeOtherException ex) {
    throw new RuntimeException(ex);
}

これが機能しない理由は、代わりに対処する必要があるより深い問題を明らかにしています。

メソッドがそれを宣言している場合throws Exception、それは広すぎます。それ以上の情報がない「何かがうまくいかない可能性がある」ことを知っていても、発信者には何の役にも立ちません。メソッドは、意味のある階層で特定の例外クラスを使用するか、適切な場合は未チェックの例外を使用する必要があります。

メソッドが非常に多くの異なる種類のチェック済み例外をスローすると、複雑すぎます。状況に応じて、複数の単純なメソッドにリファクタリングするか、適切な継承階層に例外を配置する必要があります。

もちろん、ルールには例外があります。メソッドを宣言するthrows Exceptionことは、他の人が使用する API を構成するのではなく、何らかの分野横断的なフレームワーク (JUnit、AspectJ、Spring など) によって使用される場合、完全に合理的です。

于 2016-09-27T10:37:37.247 に答える
1

instanceof 演算子を使用して同じものを書き換えることができます

try {
    // some code that can throw both checked and runtime exception
} catch (Exception e) {
    if (e instanceof RuntimeException) {
        throw e;
    } else {
        throw new RuntimeException(e);
    }
}

ただし、ソリューションはより良く見えます。

于 2016-09-27T08:17:08.087 に答える