Supposons que j'ai une classe et une méthode
class A {
void foo() throws Exception() {
...
}
}
Maintenant, je voudrais appeler foo pour chaque instance de A
livré par un flux comme:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
Question: Comment gérer correctement l'exception? Le code ne se compile pas sur ma machine car je ne gère pas les exceptions possibles qui peuvent être levées par foo (). Le throws Exception
de bar
semble être inutile ici. Pourquoi donc?
Réponses:
Vous devez encapsuler votre appel de méthode dans un autre, où vous ne lancez pas d' exceptions vérifiées . Vous pouvez toujours lancer tout ce qui est une sous-classe de
RuntimeException
.Un idiome d'emballage normal est quelque chose comme:
(L'exception de supertype
Exception
n'est utilisée qu'à titre d'exemple, n'essayez jamais de l'attraper vous-même)Ensuite , vous pouvez l' appeler avec:
as.forEach(this::safeFoo)
.la source
Si tout ce que vous voulez est d'appeler
foo
et que vous préférez propager l'exception telle quelle (sans wrapping), vous pouvez également simplement utiliser lafor
boucle de Java à la place (après avoir transformé le Stream en un Iterable avec une astuce ):C'est, du moins, ce que je fais dans mes tests JUnit, où je ne veux pas me donner la peine d'encapsuler mes exceptions vérifiées (et en fait préfère que mes tests jettent les originaux non emballés)
la source
Cette question est peut-être un peu vieille, mais parce que je pense que la «bonne» réponse ici n'est qu'une manière qui peut conduire à des problèmes cachés plus tard dans votre code. Même s'il y a une petite controverse , les exceptions vérifiées existent pour une raison.
À mon avis, la manière la plus élégante que vous puissiez trouver a été donnée par Misha ici. Agréger les exceptions d'exécution dans les flux Java 8 en effectuant simplement les actions dans "futures". Ainsi, vous pouvez exécuter toutes les pièces de travail et collecter les exceptions qui ne fonctionnent pas en une seule. Sinon, vous pouvez tous les rassembler dans une liste et les traiter plus tard.
Une approche similaire vient de Benji Weber . Il suggère de créer un type propre pour collecter les pièces fonctionnelles et non fonctionnelles.
En fonction de ce que vous voulez vraiment obtenir, un simple mappage entre les valeurs d'entrée et les valeurs de sortie s'est produit Des exceptions peuvent également fonctionner pour vous.
Si vous n'aimez aucune de ces méthodes, envisagez d'utiliser (en fonction de l'exception d'origine) au moins une exception propre.
la source
stream.map(Streams.passException(x->mightThrowException(x))).catch(e->whatToDo(e)).collect(...)
. Il faut s'attendre à des exceptions et vous permettre de les gérer comme le font les futurs.Je suggère d'utiliser la classe Google Guava Throwables
METTRE À JOUR:
Maintenant qu'il est obsolète, utilisez:
la source
Vous pouvez encapsuler et dérouler les exceptions de cette façon.
la source
Vous souhaiterez peut-être effectuer l'une des opérations suivantes:
Plusieurs bibliothèques vous permettent de le faire facilement. L'exemple ci-dessous est écrit en utilisant ma bibliothèque NoException .
la source
Manière plus lisible:
Il suffit de le cacher dans un
RuntimeException
pour le faire passerforEach()
Bien qu'à ce stade, je ne tiendrai pas contre quelqu'un s'il dit ignorer les flux et utiliser une boucle for, à moins que:
Collection.stream()
, c'est-à-dire pas une traduction directe en une boucle for.parallelstream()
la source