W tym wpisie pokażę jak można przechwytywać wiele wyjątków naraz, gdy chcemy je obsługiwać w ten sam sposób. Jest to tak zwany multicatch i jest on dostępny również w Javie, począwszy od wersji 7.
Za przykład niech posłuży nam sytuacja, w której dana metoda może rzucić jednym z wielu wyjątków, na przykład:
public void businessMethod() throws IOException, IllegalStateException, BusinessException{
gdzie BusinessException jest zdefiniowany w następujący sposób:
public BusinessException() extends IllegalStateException() {
public BusinessException(String msg) {
super(msg);
}
}
Multicatch przed Javą 7
Po użyciu tej metody musimy obsłużyć wszystkie trzy wyjątki i potrzebujemy osobny blok catch dla każdego z nich:
try {
businessMethod()
} catch (IOException ex) {
System.out.println(ex.getMessage());
} catch (BusinessException ex) {
System.out.println(ex.getMessage());
} catch (IllegalStateException ex) {
System.out.println(ex.getMessage());
}
W tym wypadku należy również pamiętać by obsłużyć wszystkie wyjątki w odpowiedniej kolejności, a konkretniej by obsłużyć BusinessException przed IllegalStateException. Jest to spowodowane faktem, że nasz własny wyjątek dziedziczy po IllegalStateException i gdyby był w kolejności po nim, to wtedy (jako że każdy BusinessException jest typu IllegalStateException), nigdy nie dochodziłoby do obsługi naszego wyjątku, ponieważ wszystko byłoby łapane w bloku catch IllegalStateException.
Multicatch i Java 7+
W Javie od wersji 7 w górę możemy zmniejszyć ilość bloków catch, jeśli chcemy obsłużyć wiele różnych wyjątków w ten sam sposób – służy do tego tak zwany mulitcatch:
try {
businessMethod()
} catch (BusinessException ex) {
System.out.println(ex.getMessage());
} catch (IllegalStateException | IOException ex) {
System.out.println(ex.getMessage());
}
Dzięki temu skraca nam się nieco składnia – wyjątki rozdzielamy znakiem |. Jednak i tu należy uważać na kwestie dotyczące dziedziczenia i hierarchii wyjątków. Ponownie BusinessException jest „problematyczny” – nie może się on znaleźć w tym samym bloku multicatch co jego rodzic – czyli IllegalStateException, wciąż musi być on obsługiwany w osobnym bloku.
Drugą różnicą, już mniej dotkliwą, jest kwestia „przepakowania” parametru ex. W „starej” Javie mogliśmy zrobić coś takiego:
catch (IOException ex) {
ex = new IOException("new message");
}
W nowszych wersjach, przy użyciu mulitcatch, nie jest to już możliwe – parametr ex jest niejawnie typu final.
Podsumowanie
I to by było na tyle jeżeli chodzi o temat multicatch w Javie. Na pewno warto pamiętać, że mamy takie narzędzie do dyspozycji (w zależności od tego z jakiej wersji Javy akurat korzystamy w projekcie). Natomiast korzystając już z multicatcha oraz pracując z wyjątkami, które sami utworzyliśmy, nie zapominajmy o hierarchii dziedziczenia.