Załóżmy, że mam klasę i metodę
class A {
void foo() throws Exception() {
...
}
}
Teraz chciałbym wywołać foo dla każdej instancji A
dostarczonej przez strumień:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
Pytanie: Jak prawidłowo obsłużyć wyjątek? Kod nie kompiluje się na moim komputerze, ponieważ nie obsługuję możliwych wyjątków, które mogą być generowane przez foo (). throws Exception
Z bar
wydaje się być bezużyteczne tutaj. Dlaczego?
java
java-8
unhandled-exception
java-stream
Bastian
źródło
źródło
Odpowiedzi:
Musisz zawinąć wywołanie metody w inne, w którym nie rzucasz sprawdzonych wyjątków . Nadal możesz wrzucić wszystko, co jest podklasą
RuntimeException
.Normalny idiom zawijania to coś takiego:
(Wyjątek nadtypu
Exception
jest używany tylko jako przykład, nigdy nie próbuj go złapać samodzielnie)Następnie można wywołać go z:
as.forEach(this::safeFoo)
.źródło
Jeśli chcesz tylko wywołać
foo
i wolisz propagować wyjątek tak, jak jest (bez zawijania), możeszfor
zamiast tego po prostu użyć pętli Java (po przekształceniu strumienia w iterowalny z pewnymi sztuczkami ):To jest przynajmniej to, co robię w moich testach JUnit, w których nie chcę robić kłopotu z zawijaniem moich sprawdzonych wyjątków (i tak naprawdę wolę, aby moje testy rzucały niezapakowane oryginalne)
źródło
To pytanie może być trochę stare, ale ponieważ uważam, że „właściwa” odpowiedź jest tylko jednym sposobem, który może prowadzić do pewnych problemów ukrytych w dalszej części kodu. Nawet jeśli jest trochę kontrowersji , nie bez powodu istnieją zaznaczone wyjątki.
Moim zdaniem najbardziej elegancki sposób, jaki można znaleźć, podał Misha tutaj Zagreguj wyjątki środowiska uruchomieniowego w strumieniach Java 8, wykonując po prostu akcje w „futures”. Możesz więc uruchomić wszystkie działające części i zebrać niedziałające wyjątki jako jedną. W przeciwnym razie możesz zebrać je wszystkie na liście i przetworzyć je później.
Podobne podejście wywodzi Benji Weber . Sugeruje stworzenie własnego typu do zbierania części roboczych i niepracujących.
W zależności od tego, co naprawdę chcesz osiągnąć, proste mapowanie między wartościami wejściowymi a wartościami wyjściowymi wystąpiły Wyjątki mogą również działać dla Ciebie.
Jeśli nie podoba ci się żaden z tych sposobów, rozważ użycie (w zależności od oryginalnego wyjątku) przynajmniej własnego wyjątku.
źródło
stream.map(Streams.passException(x->mightThrowException(x))).catch(e->whatToDo(e)).collect(...)
. Powinien spodziewać się wyjątków i pozwalać na traktowanie ich jak w przypadku przyszłości.Proponuję użyć klasy Google Guava Throwables
AKTUALIZACJA:
Teraz, gdy jest przestarzały, użyj:
źródło
W ten sposób możesz zawijać i rozpakowywać wyjątki.
źródło
Możesz wykonać jedną z następujących czynności:
Kilka bibliotek pozwala to łatwo zrobić. Poniższy przykład został napisany przy użyciu mojej biblioteki NoException .
źródło
Bardziej czytelny sposób:
Po prostu ukryj to,
RuntimeException
aby to ominąćforEach()
Chociaż w tym momencie nie będę się sprzeciwiać komuś, kto powie, że pomiń strumienie i pójdę z pętlą for, chyba że:
Collection.stream()
, tj. nie jest to proste tłumaczenie do pętli for.parallelstream()
źródło