J'apprécie beaucoup les nouvelles fonctionnalités de Java 8 concernant les interfaces de méthode lambdas et par défaut. Pourtant, je me lasse toujours des exceptions vérifiées. Par exemple, si je veux juste lister tous les champs visibles d'un objet, j'aimerais simplement écrire ceci:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
Cependant, comme la get
méthode peut générer une exception vérifiée, ce qui ne correspond pas au Consumer
contrat d'interface, je dois alors intercepter cette exception et écrire le code suivant:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
Cependant, dans la plupart des cas, je souhaite simplement que l'exception soit émise en tant que RuntimeException
et laisse le programme gérer, ou non, l'exception sans erreurs de compilation.
Je voudrais donc connaître votre opinion sur la solution de contournement controversée que je propose pour la gêne des exceptions vérifiées. À cette fin, j'ai créé une interface auxiliaire ConsumerCheckException<T>
et une fonction utilitaire rethrow
( mise à jour conformément à la suggestion du commentaire de Doval ) comme suit:
@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;
}
}
Et maintenant je peux juste écrire:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
Je ne suis pas sûr que ce soit l'idiome le plus approprié pour contourner les exceptions vérifiées, mais comme je l'ai expliqué, j'aimerais disposer d'un moyen plus pratique de réaliser mon premier exemple sans traiter des exceptions vérifiées. C'est le moyen le plus simple que j'ai trouvé. pour le faire.
sneakyThrow
dans rethrow
pour lancer l'original, exception vérifiée au lieu de l'envelopper dans un fichier RuntimeException
. Vous pouvez également utiliser l' @SneakyThrows
annotation de Project Lombok qui fait la même chose.
Consumer
s in forEach
peut être exécuté de manière parallèle lors de l’utilisation de Stream
s parallèles . Un jetable généré chez le consommateur se propage ensuite vers le fil appelant, ce qui 1) n'arrête pas les autres consommateurs exécutant simultanément, ce qui peut ou non être approprié, et 2) si plus d'un consommateur jette quelque chose, uniquement l'un des objets jetables sera vu par le fil d'appel.