Java 16 - co nowego?
Właśnie pojawiła się nowa wersja Javy, czyli Java 16. Jakiś czas temu pisaliśmy o tym, co znalazło się w JDK 16, czyli implementacji zmian, które wprowadza się w tym języku przed oficjalnym wydaniem nowej wersji, i było ich całkiem sporo. Tutaj rozszerzymy trochę temat, skupiając się na wszystkich nowościach w bardziej szczegółowy sposób.
W artykule tym zajmiemy się zatem takimi rzeczami, jak zmiany w języku, rozszerzenia wsparcia, wewnętrzne porządki oraz porty i narzędzia.
Nie zwlekając już zatem więcej, zobaczmy, co nowego dzieje się obecnie w Javie.
Rekordy
Wraz z nową wersją, Java została wzbogacona o rekordy, które pojawiły się już w wersjach 14 i 15 jako preview. Rekordy to klasy, które funkcjonują jak transparentne kontenery niemutowalnych danych. Motywacją jest tutaj to, że w Javie stworzenie klasy, która trzyma tylko dane, wymagało o wiele większej uwagi, niż jest to konieczne. Definiowanie akcesorów czy metod takich jak equals()
, hashCode()
, toString()
w tym przypadku to źródło frustracji i błędów.
Dobry przykład, który ilustruje możliwości rekordów możemy znaleźć w JEP 359:
record Range(int lo, int hi) {
public Range {
if (lo > hi) /* referring here to the implicit constructor parameters */
throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
}
}
Bardziej szczegółowy opis rekordów możecie znaleźć tutaj.
Pattern Matching z instanceof
Zmiana ta została po raz pierwszy zaproponowana w JEP 394 - pisaliśmy o niej przy okazji wydania Javy 14, a teraz pojawiła się już jako stabilna funkcja. Pattern rozumiemy tutaj jako zestaw predykatu do wykonania na obiekcie oraz powiązanych z nim zmiennych, które zostaną wyciągnięte z obiektu, w przypadku, gdy predykat ten będzie prawdziwy. Oto, jak to wygląda:
if (obj instanceof String s) {
// can use s here
}
Dzieją się tutaj następujące rzeczy - sprawdzamy czy obj
jest instancją String
- jeżeli tak, to zostaje utworzone s
oraz przypisany zostaje do niego wynik rzutowania obj
na String
.
Bardziej szczegółowy opis pattern matching znajdziecie tutaj.
Klasy zapieczętowane
Klasy zapieczętowane pojawią się w Javie 16 jako drugi preview. Zostały one zaproponowane w JEP 397, a ich celem jest restrykcja tego, które klasy, czy interfejsy, będą mogły rozszerzać lub implementować klasy zapieczętowane. Ma to również pozwolić autorowi klasy lub interfejsu na kontrolowanie, który kod jest odpowiedzialny za jej implementację.
Ulepszona współpraca z programami natywnymi
Foreign Linker API oferuje statycznie typowany i typowo javowy dostęp do kodu natywnego. API to, razem z Foreign-Memory API, ma znacznie uprościć proces tworzenia bindingów do natywnych bibliotek, który jest z kolei bardzo podatny na błędy.
Celem wprowadzenia tego API do Javy jest m.in. zastąpienie JNI lepszym rozwiązaniem napisanym w Javie. Co więcej, twórcy chcą tutaj zapewnić interoperacyjność z bibliotekami C.
Elastyczny metaspace
Elastyczny metaspace zwraca niewykorzystaną pamięć metadanych klas HotSpot VM do systemu operacyjnego w szybki sposób. Spowoduje to, że metaspace mniej będzie obciążać pamięć, ale zostanie przy okazji uproszczony kod dotyczący tej części.
Metaspace miało w przeszłości trochę problemów z wysokim zużyciem pamięci sterty. Celem jest tutaj zatem zastąpienie obecnego alokatora pamięci takim, który wykorzystuje algorytm bliźniaków, dzielący pamięć na partycje, w celu łatwiejszego zarządzania nią.
Takie podejście było już używane np. w kernelu Linuksa.
Porty na nowe platformy
Java 16 wspiera Alpine Linux i inne dystrybucje, które korzystają z musl
jako swojej głównej biblioteki C w architekturach x64 oraz AArch64.
musl
jest linuksową implementacją funkcji standardowej biblioteki opisanej w standardach ISO C oraz Posix. Alpine Linux jest natomiast dystrybucją szeroko stosowaną przy deploymencie w chmurze, mikroserwisach oraz środowiskach kontenerowych ze względu na mały rozmiar obrazów.
Windows/AArch64 stało się dosyć istotną platformą - jest na nią teraz duże zapotrzebowanie. Przeniesienie tam JDK jest już prawie zakończone, ale celem tej propozycji jest raczej integracja portowania z głównym repozytorium JDK.
Inne zmiany
Jeśli chodzi o pozostałe zmiany, które znajdą się w Javie, to mamy tutaj m.in. migrację projektu OpenJDK na Gita oraz GitHuba, czy też wprowadzenie ostrzeżeń dla klas opartych na wartościach.
Do Javy dodano też narzędzie do pakowania aplikacji Javy, które jest samowystarczalne. Nazywa się ono jpackage
i było w inkubatorze przez dwa ostatnie wydania.
Do inkubatora trafia też Vector API. Jak sama nazwa wskazuje, pomoże ono pracować z wektorami. Prawdopodobnie jeszcze zmieni się ono przed ostatecznym wydaniem, więc na tym etapie nie będziemy podawać więcej szczegółów.
Jeśli chodzi o inne zmiany w Javie, to mamy tutaj również wsparcie dla Unix-domain socket. Ma to rozszerzyć dziedziczone mechanizmy kanałów, tak aby obsługiwały one kanały Unix-domain socket oraz kanały server socket w java.nio.channels.
W nowej wersji pojawi się również obsługa funkcji C++ 14 w kodzie źródłowym JDK. Zmiana ta ma również dać wskazówki na temat tego, których funkcji tego języka należy używać w HotSpot VM. Warto dodać, że do momentu JDK 15 funkcje C++ w JDK były ograniczone do standardów języka C++98/03.
Podsumowanie
Java 16 przyniosła wiele naprawdę ciekawych zmian. Przede wszystkim chodzi o rekordy, które sprawią, że w wielu projektach Lombok stanie się mniej potrzebny. Dodatkowo stabilne wydanie pattern matchingu z pomocą instanceof
to o tyle dobra wiadomość, że sporo kolejnych JEP-ów zależy właśnie od tej funkcji.
Funkcje z inkubatora wskazują na to, że Java będzie lepiej pracować z kodem natywnym, co może stworzyć ciekawe możliwości.