Java 22 - wszystkie nowości
Java 22 to obecnie najnowsza dostępna szeroko wersja Javy. Trzeba pamiętać, że jest to pierwsza wersja po wydaniu LTS, czyli Javie 21, więc dużo tu będzie nowości w inkubatorze czy preview. W nowej wersji pojawiło się 12 JEP-ów. Omówimy je wszystkie.
Zmiany składni Javy
Od czasu Javy 8 dodano sporo konstrukcji składniowych znanych z innych języków. Jedną z takich konstrukcji są nienazwane zmienne i wzorce (JEP-456), która trafia jako stabilna zmiana do Javy 22.
W wielu językach, chociażby w Pythonie czy JavaScripcie, konwencją jest przypisywanie nieużywanych zmiennych do _
. Do tej pory nie było takiej opcji w Javie, więc nawet jeżeli zmienna nie była nam potrzebna trzeba było nadać jej nazwę. Teraz nie jest to konieczne, więc zamiast:
static int count(Iterable<Order> orders) {
int total = 0;
for (Order order : orders) // order is unused
total++;
return total;
}
W Javie 22 można napisać:
static int count(Iterable<Order> orders) {
int total = 0;
for (Order _ : orders) // Unnamed variable
total++;
return total;
}
Podobnie można robić dla wzorców:
switch (ball) {
case RedBall _ -> process(ball); // Unnamed pattern variable
case BlueBall _ -> process(ball); // Unnamed pattern variable
}
Pozostałe zmiany składniowe w nowej wersji nie są jeszcze stabilne, natomiast i tak szybko je omówimy.
Pierwsza z nich to możliwość wykonywania instrukcji przed użyciem super
w konstruktorze (JEP-447). Przedtem najpierw wywoływało się super
, a dopiero potem można było dodać inne instrukcje. Dla poprawności - technicznie można było mieć kod przed super
, ale jest kilka warunków, które musiał spełnić, by się to skomplikowało i finalnie całość nie była zbyt użyteczna w większości scenariuszy. Było to irytujące, szczególnie, jeżeli podklasa musiała wykonać jakąś logikę w celu np. sprawdzenia czy podane argumenty mają sens. To oczywiście może prowadzić do dodatkowej pracy.
Dzięki tej zmianie można napisać np. coś takiego:
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
if (value <= 0)
throw new IllegalArgumentException("non-positive value");
super(value);
}
}
Pozostałe JEP-y dotyczące języka są znane z poprzednich wersji Javy czy to jako preview czy to z inkubatora. Są to:
- JEP-459: Szablony dla ciągów znaków, czyli taka interpolacja na sterydach. Wygląda to tak:
String name = "Joan"; String info = STR."My name is \{name}";
- JEP-453: Klasy i main deklarowane nie wprost, czyli opcja na skrócenie Hello World w Javie, co teraz można przedstawić tak:
void main() { System.out.println("Hello, World!"); }
Obydwie nowości omawialiśmy przy okazji Javy 21.
Obsługa kodu poza JVM
W Javie pojawiły się dwie nowości z tym związane.
Przede wszystkim mamy JEP-454, który dodaje API do obsługi obcych funkcji i pamięci. Pierwsze efekty prac nad tym API były dostępne jeszcze w Javie 17, a więc w 2021 roku. Od tego czasu każda wersja Javy dodawała nowości w tych API, a teraz w końcu mamy wersję stabilną.
Celem nowego API jest zastąpienie JNI czymś bardziej stabilnym, ale też napisanym w czystej Javie, szybkim i bezpiecznym. Tak więc, jeżeli używasz JNI w swojej pracy, to warto przyjrzeć się czy nowe API wpasowuje się w Twoje wymagania.
Skoro o JNI mowa, to JEP-423 wprowadza tzw. Region Pinning dla garbarge collectora G1. Celem jest tu to, żeby nie trzeba było wyłączać GC dla regionów krytycznych właśnie w JNI, a więc efektem ma być lepsze zarządzanie pamięcią.
Inne ciekawe nowości
Interesujący jest JEP-457, czyli nowe API do modyfikacji klas w Javie. Celem jest tu wyrzucenie ASM i zapewnienie lepszego narzędzia do tworzenia i modyfikacji klas w Javie za pomocą kodu. Będzie to przydatne dla wielu twórców narzędzi asystujących w kodowaniu, pewnie nieco mniej będą tego używać zwykli programiści. To nowość preview.
W Javie 11 pojawiła się możliwość uruchomienia pojedynczego, nieskompilowanego pliku w Javie za pomocą prostej komendy. Teraz natomiast tych plików może być więcej. Załóżmy, że mamy takie pliki:
Prog1.java
Prog2.java
Helper.java
library1.jar
library2.jar
Jeżeli uruchomimy taką komendę:
java --class-path '*' Prog1.java
To launcher Javy załaduje wszystkie pliki JAR do classpath i znajdzie odpowiednie, potrzebne klasy w odpowiednich plikach. Jest to stabilny feature w Javie 22.
W wersji preview trafiają do Javy tzw. Stream gatherers (JEP-461), czyli nowe API do obsługi strumieni, które pozwala wykonywać na strumieniu niestandardowe akcje (które teoretycznie są trudne do osiągnięcia z użyciem standardowych operacji). Jest to nieco podobne do collect
, z tym, że gather jest zaprojektowany by obsługiwać kroki pośrednie.
Zostały nam jeszcze 3 JEP-y do opisania, ale wszystkie z nich już były opisywane przez nas wcześniej.
Pierwsze 2 to dotyczą współbieżności. Mowa tu o:
- ustrukturyzowanej współbieżności (JEP-462) - która traktuje grupy spokrewnionych zadań, działających na różnych wątkach, jako pojedynczy byt, dzięki czemu łatwiej jest nimi zarządzać.
- Scoped variables (JEP-464) - które ułatwiają dzielenie niezmiennych danych między wątkiem i jego dziećmi.
Kolejna to API do obsługi wektorów (JEP-460). To już 7 wersja, która grzeje się w inkubatorze. Kto wie, może niedługo się coś z tego wykluje.
Ocena Javy 22
To, że w Javie 22 będzie mało stabilnych zmian było do przewidzenia. W nowym cyklu wydawniczym zwykle pierwsza wersja po LTS to głównie wprowadzanie nowych konceptów, które będą dojrzewać, by były stabilne i dobrze przetestowane przed kolejnym LTS-em.
Dokładnie tak się stało w tym wydaniu. Patrząc na stabilne funkcje można wnioskować, że prace nad API obcych funkcji i pamięci zajęły więcej, niż zakładano, bo to tak naprawdę jedyna duża i stabilna nowość Javy 22. Pozostałe zmiany to nadal dokładanie funkcji znanych z innych języków, tak by ułatwiać życie programistom Javy.
Na tym etapie trudno się spodziewać w Javie rewolucji i wszystkie zmiany to odzwierciedlają. Mamy do czynienia z powolnym usprawnianiem składni oraz naprawianiem nie domagających systemów.