Aprecio mucho las nuevas características de Java 8 sobre las interfaces de métodos predeterminados y lambdas. Sin embargo, todavía me aburro con las excepciones comprobadas. Por ejemplo, si solo quiero enumerar todos los campos visibles de un objeto, me gustaría simplemente escribir esto:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
Sin embargo, dado que el método get
puede generar una excepción marcada, que no está de acuerdo con el contrato de interfaz Consumer
, entonces debo capturar esa excepción y escribir el siguiente código:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
Sin embargo, en la mayoría de los casos, solo quiero que la excepción se lance como RuntimeException
y deje que el programa maneje, o no, la excepción sin errores de compilación.
Por lo tanto, me gustaría conocer su opinión sobre mi polémica solución para el problema de las excepciones verificadas. Para ese fin, creé una interfaz auxiliar ConsumerCheckException<T>
y una función de utilidad rethrow
( se actualizó según la sugerencia de Comentario de Doval ) de la siguiente manera:
@FunctionalInterface
public interface ConsumerCheckException<T>{
void accept(T elem) throws Exception;
}
public class Wrappers {
public static <T> Consumer<T> rethrow(ConsumerCheckException<T> c) {
return elem -> {
try {
c.accept(elem);
} catch (Exception ex) {
/**
* within sneakyThrow() we cast to the parameterized type T.
* In this case that type is RuntimeException.
* At runtime, however, the generic types have been erased, so
* that there is no T type anymore to cast to, so the cast
* disappears.
*/
Wrappers.<RuntimeException>sneakyThrow(ex);
}
};
}
/**
* Reinier Zwitserloot who, as far as I know, had the first mention of this
* technique in 2009 on the java posse mailing list.
* http://www.mail-archive.com/[email protected]/msg05984.html
*/
public static <T extends Throwable> T sneakyThrow(Throwable t) {
throw (T) t;
}
}
Y ahora solo puedo escribir:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
No estoy seguro de que este sea el mejor modismo para cambiar las excepciones comprobadas, pero como expliqué, me gustaría tener una forma más conveniente de lograr mi primer ejemplo sin tratar las excepciones comprobadas y esta es la forma más sencilla. que encontré para hacerlo.