zadanie java maszyna losująca
Maszyna losująca
22 sierpnia 2016
serializacja artykuł
Serializacja w języku Java
2 września 2016
try-with-resources

Artykuł opisuje konstrukcję try-with-resources występującą w języku Java. Na przykładowym programie będziesz mógł dowiedzieć się jak ona działa. W artykule przeczytasz też o tym czym jest „cukier syntaktyczny”. Całość zakończymy jak zwykle zadaniem, które pozwoli Ci przećwiczyć materiał opisany w artykule. Zapraszam!

To jest jeden z artykułów w ramach darmowego kursu programowania w Javie. Proszę zapoznaj się z pozostałymi częściami, mogą one być pomocne w zrozumieniu materiału z tego artykułu.

Try-with-resources

Pamiętasz w jaki sposób musieliśmy obchodzić się ze strumieniami danych? Trzeba było koniecznie pamiętać o ich zamknięciu. Generowało to sporą masę powtarzalnego kodu (ang. boilerplate code). Dobrą praktyką jest unikanie, powtórzeń – mniej kodu źródłowego, mniej miejsc do popełniania potencjalnego błędu :). Tutaj z pomocą przyszli twórcy Javy, wprowadzając konstrukcję „try-with-resources”.

Tego typu konstrukcję możemy nazwać cukrem syntaktycznym (ang. syntactic sugar). Takie konstrukcje upraszczają kod, jednak nie są niezbędne dla języka programowania. Innymi słowy programista mógłby sobie bez takich konstrukcji poradzić, jednak ich obecność zmniejsza ilość kodu, która jest potrzebna do wykonania tego samego zadania.

Najlepiej będzie jeśli zobaczymy to na przykładzie. Poniższy fragment kodu prezentuje odczytanie linijki z pliku tekstowego. W tym przykładzie także obsługujemy wyjątki, nie są one wspomniane w sygnaturze metody po klauzuli throws więc odpowiednie bloki catch muszą się znaleźć aby kompilator pozwolił nam ten kod skompilować (pamiętasz wyjątki typu checked i unchecked?)

Prawda, że dużo tego? I tu z pomocą przychodzi konstrukcja try-with-resources, zobacz proszę jak ona wygląda:

Konstrukcja wygląda jak try/catch z tym, że przez blokiem objętym try możemy zainicjalizować zmienne, które zostaną automatycznie zamknięte. Kompilator widząc konstrukcję try-with-resources wygeneruje za nas kod zbliżony do tego z pierwszego przykładu (w podobny sposób generuje np. domyślne konstruktory).

Konstrukcję try-with-resources możemy nazwać także „menadżerem kontekstu”, automatycznie zarządza ona za nas kontekstem, w ramach którego dostępne są zmienne zdefiniowane wewnątrz nawiasów (). Co więcej, wewnątrz tych nawiasów możemy zainicjalizować więcej zmiennych, każda z nich zostanie poprawnie zamknięta (zostanie na nich wywołana metoda close). W przykładzie poniżej odczytujemy linijkę z pliku wejściowego i zapisujemy ją do pliku wyjściowego (tutaj pominąłem obsługę wyjątków):

Taka struktura tłumaczona jest przez kompilator na sekwencję zagnieżdżonych bloków try/catch/finally. W każdym z tych zagnieżdżonych bloków zarządza kolejną zmienną. Zmienne zamykane są w odwrotnej kolejności niż są deklarowane, zatem w naszym przykładzie pierwszy zostanie zamknięty fileWriter po nim fileReader.

Własne menadżery kontekstu

Całość działa, ponieważ klasy takie jak BufferedFileWriter czy BufferedFileReader implementują interfejs java.lang.AutoCloseable. Właściwie to wszystkie znane mi klasy do obsługi strumieni wejściowych/wyjściowych w standardowej bibliotece Javy implementują ten interfejs. To jest właśnie główne wymaganie, które musi być spełnione przez zmienne definiowane wewnątrz () gdy używamy konstrukcji try-with-resources.

Nasunąć się zatem może pytanie, czy  możemy stworzyć własną klasę, która będzie działała z tą konstrukcją? Oczywiście! 🙂 Poniżej przykład:

MyContextManager implementuje interfejs AutoCloseable dzięki czemu możemy użyć go wewnątrz konstrukcji try-with-resources. Jeśli uruchomiłbyś metodę main z powyższego przykładu na konsoli pojawiłyby się następujące linijki:

Widzisz? Metody close nie wywoływałem nigdzie a mimo to została automatycznie wykonana podczas działania programu. Stało się tak właśnie dzięki kompilatorowi, który przetłumaczył konstrukcję try-with-resources na kod, który poprawnie zamyka zmienne.

Zadanie

Teraz nadszedł czas na zadanie dla Ciebie. Strony w internecie tworzone są przy pomocy HTML, jest to język znaczników, który jest  interpretowany przez przeglądarki internetowe wyświetlające strony www. Przykładem znaczników jest para <em></em>, jak widzisz jest tu znacznik otwierający <em> oraz zamykający </em> (akurat ta para odpowiedzialna jest za wyróżnianie tekstu). Wewnątrz znaczników znajduje się treść np. <em>tekst</em>. Istnieje wiele innych par znaczników np. <pre></pre>, <code></code>, <b></b> itd.,

Zaimplementuj klasę HtmlTag, która będzie menadżerem kontekstu. W konstruktorze powinna przyjmować nazwę znacznika np. em. Klasa powinna mieć metodę body, która przyjmie parametr typu String i wypisze go na konsoli. Uruchamiając kod

Na konsoli powinien znaleźć się tekst

Jak zwykle zachęcam do samodzielnego rozwiązania zadania, jeśli jednak utknąłbyś przygotowałem przykładowe rozwiązanie, które może Ci pomóc.

Materiały dodatkowe

Podsumowanie

Po przeczytaniu artykułu wiesz już jak używać konstrukcji try-with-resources, wiesz czym jest cukier syntaktyczny. Mam nadzieję, że spędziłeś trochę czasu rozwiązując zadanie, które pozwoliło Ci przećwiczyć wiedzę w praktyce. Na koniec mam do Ciebie wielką prośbę, zależy mi na dotarciu do jak największej liczby czytelników, możesz mi w tym pomóc polecając bloga znajomym i udostępniając link na facebooku, z góry dziękuję i do następnego razu.

[FM_form id=”3″]

Zdjęcie dzięki uprzejmości https://www.flickr.com/photos/livinginmonrovia