Co nowego wnosi JAVA 14?

Nowy cykl wydawania Javy nie jednego może przyprawić o zawrót głowy.
Java 14 puka do naszych drzwi z pokaźnym zestawem ulepszeń. Postaram się przedstawić w pigułce wszystko to, co trzeba o nich wiedzieć:

1. JEP 305 – Pattern Matching for instanceof.

Instanceof zyskuje możliwość deklaracji zmiennej przy sprawdzaniu typu:

if (input instanceof Number number) {
    int x = number.intValue();
    ...
}

Jak widać “input” jest bezpiecznie rzutowany na typ “Number”. Nie jest to żadna rewolucyjna zmiana. Ulepszenie to pomaga tworzyć zwięzłe konstrukcje z użyciem “instanceof”.

2. JEP 343 – Packaging Tool.

Jpackage to eksperymentalne narzędzie do tworzenia aplikacji uruchamianych na docelowym systemie operacyjnym. Ma pomóc w spakowaniu wszystkiego, co jest potrzebne do pracy programu. Dostajemy wsparcie trzech systemów:

  • Linux: deb i rpm
  • macOs: pkg i dmg
  • Windows: msi i exe

Dziwne, że aż tyle musieliśmy czekać na rozwiązanie dostarczone z Javą. A przecież powstało wiele komercyjnych narzędzi robiących dokładnie to samo.

3. JEP 349 – JFR Event Streaming.

Ulepszona wersja standardowego JDK Flight Recorder, pozwala na streamowanie eventów z JMX. Rozwiącanie to pozwala na prezentacje danych natychmiastowo. Przed zmianią wymagane było zrobienie nagrania i późniejsza jego analiza. Jest to drobne poprawienie możliwości debugowania uruchomionych aplikacji.

4. JEP 358 – Helpful NullPointerExceptions.

Nie mogłem uwierzyć, kiedy po raz pierwszy zobaczyłem wzmiankę o tej poprawce. W końcu król wszystkich błędów doczekał się sensownego logowania. NPE jest niesamowicie częstym błędem. Wyjątkowo trudną sytuacją są linie zawierające wiele instrukcji lub zagnieżdżeń obiektów. W takim wypadku standardowy komunikat błędu jest bardzo mało przydatny. Dla przykładu taka konstrukcja:

obj.metoda1(param1).metoda2(param2).metoda3(param3);

W tym wypadku NPE nie daje nam żadnej przydatnej informacji:

Exception in thread "main" java.lang.NullPointerException
	at Main.main(Main.java:12)

W Java 14 możemy dostać taki komunikat:

Exception in thread "main" java.lang.NullPointerException:
  Cannot invoke "Test.metoda1(java.lang.Integer)" because "<param1>" is null
	at Main.main(Main.java:12)

Taki komunikat mówi nam dokładnie, gdzie i dlaczego dostaliśmy NPE.

Moim zdaniem jest to najprzydatniejsza zmiana ze wszystkich. W końcu możliwe będzie wyczytanie jednoznacznie jaka jest przyczyna wystąpienia NPE. Ze względu na częstość tego błędu, takie logowanie może zaoszczędzić masę czasu.

Co ciekawe jest to funkcja eksperymentalna i musimy użyć odpowiednie opcji by ją włączyć:

-XX:+ShowCodeDetailsInExceptionMessages

Mam nadzieję, że w Java 15 będzie ta funkcja będzie włączona domyślnie.

5. JEP 359 – Records.

Kolejna bardzo ciekawa zmiana eksperymentalna (musimy ustawić opcję –enable-preview by się nią cieszyć w Java 14). Rekord to nic innego jak niezmieniane DTO. Deklaracja jest bardzo prosta:

record Coordinates(double lat, double lon) { }

Wszystkie potrzebne metody i pola są automatycznie dodawane przez kompilator. Rekord ma następujące właściwości:

  • jest to klasa finalna rozszerzająca java.lang.Record.
  • prywatne finalne zmienne wymienione w deklaracji rekordu
  • domyślny konstruktor ze wszystkim zmiennymi
  • domyślny toString()
  • domyślne hashCode() i equals()
  • gettery dla wszystkich zmiennych
  • brak setterów

Kiedy spojrzałem na nią od razu do głowy przyszedł mi projekt Lombok. Mam mieszane uczucia do tej zmiany. Z jednej strony jest to krok w dobrym kierunku. Java od dawna potrzebuje eliminacji boiler-plate kodu, który powstaje najczęściej przy klasach typu DTO. Z drugiej strony Lombok załatwia te problemy używając jednej adnotacji.

Osobiście zostaje przy Lomboku, który załatwia nie tylko to, co daje rekord, ale ma też masę innych przydatnych funkcji.

6. JEP 361 – Switch Expressions.

Od wersji 14 nowy switch jest w standardzie i nie musimy używać opcji –enable-preview.

7. JEP 368 – Text Blocks.

Bloki tekstowe nadal pozostają w fazie eksperymentalnej (musimy ustawić opcję –enable-preview). W wersji 14 zostały dodane dwie sekwencje ucieczki:

  • “\” – zapobiega zakończeniu linii
  • “\s” – pozwala na użycie spacji na końcu linii

Najlepiej zobrazować tą zmianę na przykładach:

String block = """
               linia1\
               linia2
               linia3
               """;

Wynikowy string to:

linia1linia2
linia3

Jak widzimy “\” pozwala na pominięcie znaku nowej linii (\n), który jest standardowo dodawany na końcu.

String block = """
               linia1\s
               linia2
               """;

Wynikowy string to:

linia1·
linia2

Dzięki “\s” można dodać spacje na końcu wiersza, które bez niego były by zignorowane przez kompilator.

Bloki tekstowe to bardzo przydatna zmiana. Długie teksty zawsze były ogromnym problemem w kodzie Java. Czekam z niecierpliwością na ostateczną wersję tej poprawki.

8. JEP 370 – Foreign-Memory Access API.

Nie musimy już hackować klasy Unsafe w celu dostępu do pamięci natywnej. Wersja 14 daje nam interfejs dostępu bezpośredniego do bloków pamięci. Możemy to zastosować do implementacji funkcji wymagających maksymalnej wydajności.

Nie polecał bym używania tej funkcji, chyba że jest absolutnie konieczne. Wzrost wydajności zwykle nie jest warty zwiększenia skomplikowania implementacji. Jeśli jednak zdecydujemy się na to rozwiązanie, to musimy dodać odpowiedni moduł przy kompilacji i uruchamianiu aplikacji:

javac --add-modules jdk.incubator.foreign Main.java
java --add-modules jdk.incubator.foreign Main

Po dodaniu modułu możemy używać klas MemoryHandles i MemorySegment.

Kilka słów podsumowania.

JAVA 14 dostarcza wiele małych zmian technologicznych, które nie mają wpływu na sam język. Pozwalam sobie na ich pominięcie, żeby skoncentrować się na wszystkim tym, co trzeba wiedzieć z perspektywy programowania. Zachęcam do lektury wszystkich zmian na https://openjdk.java.net/projects/jdk/14/.

Leave A Comment