web-dev-qa-db-ja.com

一般的に指定された例外をスローしないようにするにはどうすればよいですか?

「プロデューサー」インターフェースを作成しました(メソッド参照で使用するため、それぞれ単体テスト用に簡単にモック化します):

@FunctionalInterface
public interface Factory<R, T, X extends Throwable> {
    public R newInstanceFor(T t) throws X;
}

私の最初のユースケースは実際にいくつかのチェック済みWhateverExceptionをスローする必要があったので、私はそのように作成しました。

しかし、私の2番目の使用例では、スローするXがありません。

コンパイラーを幸せにするために思いつくことができる最高のものは次のとおりです。

Factory<SomeResultClass, SomeParameterClass, RuntimeException> factory;

それはコンパイルされ、私が必要とすることを行いますが、それでも醜いです。その単一のインターフェースを保持する方法はありますが、特定のインスタンスを宣言するときにXを提供しませんか?

それを行う唯一の方法はサブクラス化です-しかし、あなたはそれを知っていたと思います。私の議論をより強くするために、BinaryOperatorを拡張するBiFunctionを見てください。

12
Eugene

Javaではできません。唯一の方法は、サブインターフェイスを作成することです。

public interface DefaultExceptionFactory<R, T>
        extends Factory<R, T, RuntimeException>
12
Leo Aso

これはより「ソーシャルエンジニアリング」の答えです。ラムダフォームに何もスローしないという契約を置きます。

public interface Factory<T, R, X> {

    public R newInstanceFor(T arg) throws X;

    public static Factory<R, U, AssertionError> neverThrows(Factory<U, V, ?> input) {
        return u -> {
            try {
                return input.newInstanceFor(u);
            }
            catch(Throwable t) {
                throw new AssertionError("Broken contract: exception thrown", t);
            }
        };
    }
}

使用法は次のようになります。

class MyClass {
    Factory<MyInput, MyOtherClass, AssertionError> factory;

    MyClass(Factory<MyInput, MyOtherClass, ?> factory) {
        this.factory = Factory.neverThrows(factory);
    }

    public void do() {
      factory.newInstanceFor(new MyInput()).do();
    }
}

このアプローチの欠点:タイプシグネチャでコントラクトを実際に指定することはできません。コントラクトは実装の詳細になります。これを型シグネチャに含める場合は、2番目のサブインターフェイスが必要になります。

5
M. Prokhorov

可能であれば、以下のコードのようなジェネリックとしてメソッドを定義できます。

@FunctionalInterface
public interface Factory<R, T> {
    public <X extends Throwable> R newInstanceFor(T t) throws X;
}
3
Beno Arakelyan

Project Lombok@ SneakyThrows アノテーションを使用できます:

@FunctionalInterface
public interface Factory<R, T> {

    @SneakyThrows
    R newInstanceFor(T t);
}

これにより、任意の例外(チェックありまたはチェックなし)をスローできます。ただし、この機能は慎重に扱う必要があるため、ドキュメントをお読みください。

0
foundationer