tutorial lambdas expressions example java lambda java-8

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