Java8 Lambda 및 예외
누군가가 나에게 다음과 같은 이상한 점을 설명해 줄 수 있는지 궁금합니다. Java 8 업데이트 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
이것은 Eclipse에 영향을 미치지 않는 버그 JDK-8054569 의 경우처럼 보입니다 .
Function을 Supplier로 바꾸고 orElseThrow
메서드를 추출하여 범위를 좁힐 수있었습니다 .
abstract <T> void f(Supplier<T> s);
abstract <T, X extends Throwable> T g(Supplier<? extends X> x) throws X;
void bug() {
f(() -> g(() -> new RuntimeException("foo")));
}
그리고 공급자와 람다를 모두 제거하여 추가로 :
abstract <T> void f(T t);
abstract <T, X extends Throwable> T g(X x) throws X;
void bug() {
f(g(new RuntimeException("foo")));
}
which is actually a cleaner example than the one in the bug report. This shows the same error if compiled as Java 8, but works fine with -source 1.7
.
I guess something about passing a generic method return type to a generic method parameter causes the type inference for the exception to fail, so it assumes the type is Throwable and complains that this checked exception type isn't handled. The error disappears if you declare bug() throws Throwable
or change the bound to X extends RuntimeException
(so it's unchecked).
This is what solved the problem for me:
instead of writing
optional.map(this::mappingFunction).orElseThrow(() -> new BadRequestException("bla bla"));
I wrote:
optional.map(this::mappingFunction).<BadRequestException>orElseThrow(() -> new BadRequestException("bla bla"));
Adding the explicit <BadRequestException>
helps with these lambda edge cases (which are quite annoying...)
UPDATE: This is in case you can't update to the latest JDK version, if you can you should...
If you are trying to compile someone else's project try to upgrade to 1.8.0_92
Similar to @keisar I could solve my problem (see maven-compiler-plugin fails to compile a file that Eclipse has no problem with) by specifying the type parameter.
However, I found it much more convenient (since I use NotFoundException
in a number of places) to simply make my exception class its own Supplier
:
public class NotFoundException extends RuntimeException
implements Supplier<NotFoundException> {
// Rest of the code
@Override
public NotFoundException get() {
return this;
}
}
Then you can simply do:
// Distribution.rep().get(id) returns a java.util.Optional
Distribution distro = Distribution.rep().get(id).orElseThrow(
new NotUniqueException("Exception message"));
참고URL : https://stackoverflow.com/questions/25523375/java8-lambdas-and-exceptions
'development' 카테고리의 다른 글
파이썬으로 백 슬래시를 인쇄하는 방법? (0) | 2020.11.14 |
---|---|
Bootstrap의 툴팁은 마우스를 올리면 표 셀을 오른쪽으로 약간 이동합니다. (0) | 2020.11.14 |
플렉스 아이템이 플렉스 컨테이너의 높이를 채우지 않게 만드는 방법은 무엇입니까? (0) | 2020.11.14 |
LINQ를 사용하여 DataColumnCollection 쿼리 (0) | 2020.11.14 |
JavaScript의 ASCII 값에서 문자열 또는 문자를 만드는 방법은 무엇입니까? (0) | 2020.11.14 |