expressions - Java8 Lambdas y Excepciones
lambda expressions (3)
Me pregunto si alguien podría explicarme la siguiente rareza. Estoy usando la actualización 11 de Java 8.
Dado este método
private <F,T> T runFun(Function<Optional<F>, T> fun, Optional<F> opt) {
return fun.apply(opt) ;
}
Si primero construyo una función Object y la paso al método anterior, compilarán cosas.
private void doesCompile() {
Function<Optional<String>, String> fun = o -> o.orElseThrow(() -> new RuntimeException("nah"));
runFun(fun, Optional.of("foo"));
}
Pero, si alineo la función como un lambda, el compilador dice
excepción no reportada X; debe ser atrapado o declarado arrojado
private void doesNotCompile () {
runFun(o -> o.orElseThrow(() -> new RuntimeException("nah")), Optional.of("foo"));
}
Actualización : Resulta que el mensaje de error fue abreviado por maven. Si se compila directamente con javac, el error es:
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
También vea here código de prueba ejecutable.
Esto es lo que me solucionó el problema:
en lugar de escribir
optional.map(this::mappingFunction).orElseThrow(() -> new BadRequestException("bla bla"));
Escribí:
optional.map(this::mappingFunction).<BadRequestException>orElseThrow(() -> new BadRequestException("bla bla"));
Agregar la <BadRequestException>
explícita ayuda con estos casos de borde lambda (que son bastante molestos ...)
ACTUALIZACIÓN: Esto es en caso de que no pueda actualizar a la última versión de JDK, si puede, debería ...
Esto parece un caso de error JDK-8054569 , que no afecta a Eclipse.
Pude orElseThrow
reemplazando Función con Proveedor y extrayendo el método 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")));
}
y luego, eliminando los proveedores y lambdas por completo:
abstract <T> void f(T t);
abstract <T, X extends Throwable> T g(X x) throws X;
void bug() {
f(g(new RuntimeException("foo")));
}
que es en realidad un ejemplo más limpio que el del informe de errores. Esto muestra el mismo error si se compila como Java 8, pero funciona bien con -source 1.7
.
Supongo que algo acerca de pasar un tipo de devolución de método genérico a un parámetro de método genérico hace que la inferencia de tipo para la excepción falle, por lo que asume que el tipo es Throwable y se queja de que este tipo de excepción comprobada no se maneja. El error desaparece si declara que bug() throws Throwable
o cambia el límite a X extends RuntimeException
(por lo que está desmarcado).
Si está intentando compilar el proyecto de otra persona, intente actualizarlo a 1.8.0_92