programowanieProgramista Backend

Czym jest pattern matching w Javie, na etapie jakim został wdrożony, do czego jest używany i jakie niuanse należy znać? Podaj przykład.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Historia pytania

Pattern matching — technika zapożyczona z języków funkcyjnych i skryptowych, pozwalająca sprawdzić typ i wydobyć dane w jednym kroku. W Javie rozwój pattern matching rozpoczął się od wersji Java 14 (funkcja w zapowiedzi), poprawił się w wersjach Java 16-17, a w ostatnich wydaniach rozszerza się na konstrukcje switch.

Problem

Klasyczny sposób sprawdzania typu i rzutowania wyglądał nieporęcznie:

if (obj instanceof String) { String s = (String) obj; ... }

Pojawiały się zbędne zmienne, duża ilość kodu szablonowego i ryzyko błędów rzutowania typów.

Rozwiązanie

Pattern matching pozwala połączyć sprawdzenie typu, zadeklarowanie nowej zmiennej i użycie jej w jednym wyrażeniu:

if (obj instanceof String s) { System.out.println(s.length()); }

Podobne wzorce teraz pojawiają się w konstrukcji switch, co czyni kod bardziej zwięzłym i mniej podatnym na błędy.

Kluczowe cechy:

  • Zwięzła i bezpieczna praca z typami.
  • Zmniejszenie liczby błędów podczas rzutowania.
  • Prostota utrzymania kodu i rozszerzenia na nowe typy.

Pytania podstępne.

Czy można używać pattern matching dla klas własnych (użytkowników) czy tylko dla typów standardowych?

Można używać do dowolnych klas. Pattern matching działa dla wszystkich klas, dla których można używać instanceof.

Czy zmienna wzoru będzie dostępna poza blokiem if/switch?

Nie, zmienna zadeklarowana wewnątrz pattern matching jest widoczna tylko w obrębie bloku, w którym została stworzona (na przykład w obrębie if lub case switch).

Przykład kodu:

if (obj instanceof Integer i) { // i jest widoczna tylko w tym bloku System.out.println(i + 10); } // Tutaj i jest niedostępna

Czy można używać pattern matching z generykami?

Tak, w ten sposób:

Object list = List.of("a", "b"); if (list instanceof List<?> l) { System.out.println(l.size()); }

Jednak praca z typami raw i rzutowanie do typów parametryzowanych wciąż jest ograniczona z powodu usuwania typów.

Typowe błędy i antywzorce

  • Przypuszczenie, że pattern matching automatycznie obsługuje null: jeśli obiekt jest równy null, warunek nie zostanie spełniony (instanceof z null zawsze false).
  • Używanie pattern matching tam, gdzie wystarczy metoda getClass().
  • Zbyt częste stosowanie pattern matching może pogorszyć architekturę, jeśli intencje są niejasne.

Przykład z życia

Negatywny przypadek

Zespół wdrożył pattern matching we wszystkich przypadkach, w tym wewnętrznych DTO, klasach serwisowych i przypadkach, w których wystarczyłoby polimorfizm. Kod stał się zbyt zależny od instanceof, rola hierarchii klas została zamazana.

Plusy:

  • Szybkie wdrożenie.
  • Zwięzły styl.

Minusy:

  • Błędy architektoniczne.
  • Mniejsza czytelność.

Pozytywny przypadek

W projekcie pattern matching stosowano tylko dla ogólnych interfejsów, pomocniczych narzędzi i przetwarzania kolekcji nieznanego typu. Architektura OOP została zachowana, wzorzec stosowany tylko tam, gdzie nie można się bez niego obejść.

Plusy:

  • Czytelny kod.
  • Wsparcie architektury.

Minusy:

  • Wymaga starannego projektowania i znajomości wersji JDK.