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:
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.
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:
Minusy:
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:
Minusy: