Wyrzucanie wyjątku poza lambda wyrażenie

Rzucanie i łapanie wyjątków jest na pewno czymś bardzo potrzebnym a zarazem przydatnym. Pozwala reagować na sytuacje, na które nie mamy większego wpływu lub nawet których nie jesteśmy w stanie przewidzieć.

Wraz z Javą 1.8 pojawiły się lambda wyrażenia. Środek, który nam programistą bardzo ułatwia życie potrafi też czasem przysporzyć nie lada problemu. Przykładem może być sytuacja, w której mamy interfejs funkcjonalny z deklaracją metody, która nie wyrzuca żadnych wyjątków na zewnątrz. Na pierwszy rzut oka powiecie: „to nie problem, złapmy go w lambdzie”, okej, nie jest to zły pomysł, ale co jeśli potrzebujemy mimo wszystko „rzucić” go dalej?

Lambda wyrażenia są zastępowane definicjami metody interfejsu funkcjonalnego w fazie wykonania dzięki czemu rzucone wyjątki typu RuntimeException są wstanie wyjść na zewnątrz lambdy gdzie potem jesteśmy w stanie je przechwycić i coś z nimi zrobić.

Dosyć proste rozwiązanie mogło by się rzec, choć wpaść na nie nie jest wcale tak łatwo.
Tyle teorii, to teraz czas na praktykę. Sposób zademonstruję na metodzie forEach() klasy implementującej interfejs List.

Kompilator będzie nam w tym momencie sygnalizował, że mamy nieobsłużony wyjątek. No dobrze, ale my przecież chcemy go rzucić dalej, poza nasze wyrażenie. Problem polega na tym, że metoda accept interfejsu Consumer nie posiada klauzuli throws.

W tym przypadku rozwiązanie polega na rzuceniu RuntimeException zamiast Exeption.

Okej, ale co jeśli mamy metodę throwExceptionWhenError(), która rzuca wyjątkiem? Moglibyśmy próbować go przechwycić a potem wyrzucić jako RuntimeException.

Ale pewnie sami przyznacie, że umieszczanie takiego kodu w lambda wyrażeniu nie wygląda zbyt ładnie.
Praktycznym rozwiązaniem jest stworzenie własnego interfejsu funkcjonalnego, który będzie:

  • dziedziczył po interfejsie Consumer
  • łapał wyjątki
  • wyrzucał je jako RuntimeException

Gotowa implementacja wygląda zatem następująco:

Przez co teraz nasz kod z wykorzystaniem nowego interfejsu powinien wyglądać następująco:

Co wygląda znacznie lepiej.

Takie interfejsy możemy porobić dla każdego interfejsu funkcjonalnego z pakietu java.util.function co umili nam prace.

Oczywiście pisząc swoje implementacje interfejsów funkcjonalnych oraz metody, które z nich korzystają nie zapominajmy dodać możliwości utworzenia również interfejsu z metodą, która posiada klauzulę throws co ułatwi życie wam jak i osobą korzystającym z waszego kodu.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Time limit is exhausted. Please reload the CAPTCHA.

Post Navigation