Apprezzo molto le nuove funzionalità di Java 8 su lambdas e le interfacce dei metodi predefiniti. Tuttavia, mi annoio ancora con le eccezioni verificate. Ad esempio, se voglio solo elencare tutti i campi visibili di un oggetto, vorrei semplicemente scrivere questo:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
Tuttavia, poiché il getmetodo potrebbe generare un'eccezione controllata, che non è d'accordo con il Consumercontratto di interfaccia, allora devo prendere quell'eccezione e scrivere il seguente codice:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
Tuttavia, nella maggior parte dei casi, voglio solo generare l'eccezione come a RuntimeExceptione lasciare che il programma gestisca o meno l'eccezione senza errori di compilazione.
Quindi, vorrei avere la tua opinione sulla mia controversa soluzione alternativa per il fastidio delle eccezioni verificate. A tal fine, ho creato un'interfaccia ausiliaria ConsumerCheckException<T>e una funzione di utilità rethrow( aggiornata secondo il suggerimento del commento di Doval ) come segue:
@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/javaposse@googlegroups.com/msg05984.html
*/
public static <T extends Throwable> T sneakyThrow(Throwable t) {
throw (T) t;
}
}
E ora posso solo scrivere:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
Non sono sicuro che questo sia il modo di dire migliore per aggirare le eccezioni verificate, ma come ho spiegato, vorrei avere un modo più conveniente di ottenere il mio primo esempio senza occuparmi delle eccezioni verificate e questo è il modo più semplice che ho trovato per farlo.
sneakyThrowinside of rethrowper lanciare l'eccezione originale e controllata invece di racchiuderla in a RuntimeException. In alternativa puoi usare l' @SneakyThrowsannotazione di Project Lombok che fa la stessa cosa.
Consumers in forEachpuò essere eseguito in modo parallelo quando si usano Streams in parallelo . Un lanciatore generato dal withing del consumatore si propaga quindi al thread chiamante, che 1) non bloccherà gli altri consumatori che gestiscono contemporaneamente, il che può essere o non essere appropriato, e 2) se più di uno dei consumatori lancia qualcosa, solo uno dei lanci sarà visto dal thread chiamante.