1. ホーム
  2. java

Java8 ラムダと例外

2023-09-07 07:18:13

質問

どなたか、次のような奇妙なことを説明していただけないでしょうか。私は、Java 8 update 11 を使用しています。

このメソッドが与えられると

private <F,T> T runFun(Function<Optional<F>, T> fun, Optional<F> opt) {
   return fun.apply(opt) ;
}

まず関数Objectを作り、それを上のメソッドに渡すと、コンパイルされます。

private void doesCompile() {
    Function<Optional<String>, String> fun = o -> o.orElseThrow(() -> new RuntimeException("nah"));
    runFun(fun, Optional.of("foo"));

}

しかし、この関数をラムダとしてインライン化すると、コンパイラは次のように言います。

未報告の例外X; キャッチするか、スローされるように宣言する必要があります。

private void doesNotCompile () {
    runFun(o -> o.orElseThrow(() -> new RuntimeException("nah")), Optional.of("foo"));
}


更新 : エラーメッセージはmavenによって省略されていたことが判明しました。javacで直接コンパイルすると、このようなエラーになります。

error: unreported exception X; must be caught or declared to be thrown
            runFun(o -> o.orElseThrow(() -> new RuntimeException("nah")), Optional.of("foo"));
                                     ^
  where X,T are type-variables:
    X extends Throwable declared in method <X>orElseThrow(Supplier<? extends X>)
    T extends Object declared in class Optional

また を参照してください。 をご覧ください。

どのように解決するのですか?

私の場合はこれで解決しました。

と書く代わりに

optional.map(this::mappingFunction).orElseThrow(() -> new BadRequestException("bla bla"));

と書きました。

optional.map(this::mappingFunction).<BadRequestException>orElseThrow(() -> new BadRequestException("bla bla"));

明示的な <BadRequestException> を追加することで、ラムダのエッジケース(これはかなり厄介です...)に役立ちます。

UPDATE: これは最新のJDKバージョンにアップデートできない場合に備えてのことですが、もしできるのであればした方がいいでしょう...