Apprezzo molto le nuove funzionalità di Java 8 su lambdas e le interfacce dei metodi predefinite. Tuttavia, mi annoio ancora con le eccezioni controllate. 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 metodo get
potrebbe generare un'eccezione controllata, che non concorda con il contratto di interfaccia Consumer
, allora devo rilevare 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 che l'eccezione venga generata come RuntimeException
e che il programma gestisca o meno l'eccezione senza errori di compilazione.
Quindi, vorrei avere la tua opinione sulla mia soluzione controverso per il fastidio delle eccezioni controllate. A tal fine, ho creato un'interfaccia ausiliaria ConsumerCheckException<T>
e una funzione di utilità rethrow
( aggiornata in base alla supposizione di 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/[email protected]/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 l'idioma migliore per aggirare le eccezioni controllate, ma come ho spiegato, mi piacerebbe avere un modo più conveniente per raggiungere il mio primo esempio senza considerare le eccezioni controllate e questo è il modo più semplice che ho trovato di farlo.