Algunas personas intentan convencerte de que tienes que seguir las reglas. Escuche, pero si obedece, debe decidir usted mismo dependiendo de su situación. La realidad es que "DEBES jugar según las reglas" (no "DEBES seguir las reglas"). Solo tenga en cuenta que si no cumple con las reglas, puede haber consecuencias.
La situación no solo se aplica en la situación de Runnable
Java 8, sino también con mucha frecuencia en el contexto de Streams y otros lugares donde se han introducido interfaces funcionales sin la posibilidad de lidiar con excepciones comprobadas. Por ejemplo, Consumer
, Supplier
, Function
, BiFunction
y así sucesivamente todos han sido declarados sin instalaciones para lidiar con excepciones comprobadas.
Entonces, ¿cuáles son las situaciones y las opciones? En el texto siguiente, Runnable
es representativo de cualquier interfaz funcional que no declara excepciones, o declara excepciones demasiado limitadas para el caso de uso en cuestión.
- Usted mismo ha declarado en
Runnable
algún lugar y podría reemplazarlo Runnable
con otra cosa.
- Considere reemplazar
Runnable
con Callable<Void>
. Básicamente lo mismo, pero permite lanzar excepciones; y tiene que hacerlo return null
al final, lo cual es una leve molestia.
- Considere reemplazar
Runnable
con su propia costumbre @FunctionalInterface
que puede lanzar exactamente las excepciones que desee.
- Ha utilizado una API y hay alternativas disponibles. Por ejemplo, algunas API de Java están sobrecargadas, por lo que podría usar en
Callable<Void>
lugar de Runnable
.
- Ha utilizado una API y no hay alternativas. En ese caso, todavía no te quedan opciones.
- Puede envolver la excepción en
RuntimeException
.
- Puede piratear la excepción en una RuntimeException utilizando una conversión sin marcar.
Puedes probar lo siguiente. Es un truco, pero a veces lo que necesitamos es un truco. Porque, si una excepción debe estar marcada o desmarcada se define por su tipo, pero prácticamente debería estar definida por la situación.
@FunctionalInterface
public interface ThrowingRunnable extends Runnable {
@Override
default void run() {
try {
tryRun();
} catch (final Throwable t) {
throwUnchecked(t);
}
}
private static <E extends RuntimeException> void throwUnchecked(Throwable t) {
throw (E) t;
}
void tryRun() throws Throwable;
}
Prefiero esto new RuntimeException(t)
porque tiene un seguimiento de pila más corto.
Ahora puedes hacer:
executorService.submit((ThrowingRunnable) () -> {throw new Exception()});
Descargo de responsabilidad: la capacidad de realizar conversiones no verificadas de esta manera podría eliminarse en versiones futuras de Java, cuando la información de tipo genérico se procesa no solo en tiempo de compilación, sino también en tiempo de ejecución.