rompetroll
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 un objeto de función y lo paso al método anterior, las cosas se compilan.
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 una lambda, el compilador dice
excepción no reportada X; debe ser atrapado o declarado para ser lanzado
private void doesNotCompile () {
runFun(o -> o.orElseThrow(() -> new RuntimeException("nah")), Optional.of("foo"));
}
Actualizar: 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
Ver también aquí para el código de prueba ejecutable.
Keisar
Esto es lo que resolvió el problema para mí:
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 lo explícito <BadRequestException>
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…
-
Estoy en la última versión de Java y sigo recibiendo un error. .
getOrElseThrow(throwable me ayudó. Gracias. -Hans Wurst
28 de septiembre de 2017 a las 11:14
-
Esto ayudó, gracias, no pude actualizar porque no soy dueño de la máquina.
– Alex
17 oct 2017 a las 14:01
-
Estoy en 1.8.0_144, todavía tenía que usar su solución. Eso ayudo
– olyv
18/10/2017 a las 15:32
-
Oracle 1.8.0_171 también está roto.
– Aarón Digulla
23 de julio de 2018 a las 10:01
-
1.8.0_181 también necesita el reparto explícito.
– Sven
16 de mayo de 2019 a las 5:08
Esto parece un caso de error JDK-8054569que no afecta a Eclipse.
Pude reducirlo reemplazando Función con Proveedor y extrayendo el orElseThrow
método:
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 las 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 en realidad es un ejemplo más limpio que el del informe de error. Esto muestra el mismo error si se compila como Java 8, pero funciona bien con -source 1.7
.
Supongo que pasar un tipo de retorno 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 verificado no se maneja. El error desaparece si declaras bug() throws Throwable
o cambiar el límite a X extends RuntimeException
(así que está desmarcado).
-
Actualizado de 1.8.0_45 a 1.8.0_92 y resolvió mis problemas. Gracias
– brazo
16 mayo 2016 a las 20:08
Si está intentando compilar el proyecto de otra persona, intente actualizar a 1.8.0_92
-
¿Está seguro? Todavía tengo este error en _101 y otras personas reportan este error en _171
– Pieter De Bié
9 de noviembre de 2018 a las 12:41
Similar a @keisar, podría resolver mi problema (ver maven-compiler-plugin no puede compilar un archivo con el que Eclipse no tiene problemas) especificando el parámetro de tipo.
Sin embargo, lo encontré mucho más conveniente (ya que uso NotFoundException
en varios lugares) para simplemente hacer que mi clase de excepción sea propia Supplier
:
public class NotFoundException extends RuntimeException
implements Supplier<NotFoundException> {
// Rest of the code
@Override
public NotFoundException get() {
return this;
}
}
Entonces simplemente puedes hacer:
// Distribution.rep().get(id) returns a java.util.Optional
Distribution distro = Distribution.rep().get(id).orElseThrow(
new NotUniqueException("Exception message"));
Si agrega explícitamente <RunTimeException>
se ve feo, entonces como una solución que puede reemplazar con orElseGet()
.orElseGet(() -> throw new RunTimeException("foo"));
-
No creo que puedas lanzar una excepción en línea como esa… la declaración de lanzamiento debe estar en un bloque.
– Xavier Dury
31 de marzo de 2021 a las 13:48
-
No creo que puedas lanzar una excepción en línea como esa… la declaración de lanzamiento debe estar en un bloque.
– Xavier Dury
31 de marzo de 2021 a las 13:48
Suena como otro tipo de error de inferencia. Asegúrese de incluir información detallada sobre el compilador obtiene este error ya que Eclipse usa el suyo propio.
– Marko Topolnik
27 de agosto de 2014 a las 9:27
observe que sucede lo mismo si usa una clase anónima, por lo que no es un problema de lambda.
– usuario2504380
27 de agosto de 2014 a las 10:38
Un aparte: Eclipse compila esto muy bien, y usando
o.<RuntimeException>orElseThrow(()...
resuelve el problema, sin embargo, esto no debería ser necesario. (Creo que se informó un problema similar en otra pregunta de stackoverflow hace un tiempo, pero no lo encontré en este momento…)– marco13
27 de agosto de 2014 a las 11:42
“mvn -e” puede ser útil.
– Thorbjorn Ravn Andersen
25 de septiembre de 2015 a las 8:49