A Java 23 újdonságai

Tartalomjegyzék
Sorozatunk előző cikkében a Java 22 újdonságaival foglalkoztunk. Ma a Java 23 által bevezetett 12 innovációból szemezgetünk.
A Java 23-ban megjelenő feature-ök többsége preview, és többel közülük már sok verzióval ezelőtt elkezdtek kísérletezgetni. Ilyen szempontból a rekorder egyértelműen Vector API, ami már a nyolcadik inkubátor kiadását éli meg. A Vector API első inkubátor kiadása még a Java 16-ban jelent meg, úgyhogy jó ideje húzzák már ezt a funkciót 🙂 Kíváncsian várjuk, mikor kerül be a végleges kiadásba.
Amennyiben nincs időd elolvasni minden verzió újdonságait külön-külön (tudom, van pár :)), ezt az összesítő cikkünket javaslom. Nézzük tehát a Java 23 legfontosabb újdonságait!
ZGC: alapértelmezett Generational Mode
Bár erről szóló cikkünkben nem írtunk róla részletesen, de a Java 21-ben a kijött az ún. Generational ZGC azzal a szándékkal, hogy az előző, ún. non-generational ZGC-t elavulttá nyilvánítsák és szépen-lassan kivezessék a Java-ból.
Mi az a ZGC?
Viszont mi az a ZGC? A ZGC egy olyan GC algoritmus, amely a Java 11-ben jelent meg először kísérleti feature-ként, és a Java 15-ben véglegesítették, és többszálú, sokkal nagyobb heap kezelésére képes, mint a korábbi GC algoritmus, mindezt minimális pause time-okkal.
Mi az a GC?
A GC a garbage collector rövidítése, és nagyon egyszerűen egy olyan algoritmusról beszélünk, ami a JVM-en belüli heap-et pásztázza a memóriát (pontosabban a heap-et) és megszünteti azokat az objektumokat, amelyekre már nem mutat referencia.
Profiktól tanulnál?
Azért vagyunk, hogy segítsünk.
Ahhoz, hogy megértsük, mi történik pontosan, menjünk vissza a C nyelvre egy pillanat erejéig. Ha a C-ben létrehozok valamit a heap-en (malloc függvény), akkor a lefoglalt memóriaterület felszabadításáról nekem kell gondoskodnom: meghívom a free függvényt, amikor már nincs szükségem az adott adatra.
Ezzel szemben a Java-ban az objektumok megszüntetéséről egy automatizmus gondoskodik, és ezzel levesz egy nagyon fontos felelősséget a fejlesztő válláról.
Mi az a pause time?
Két bekezdéssel feljebb említettem, hogy a ZGC esetében minimális a pause time – na de mi az? A pause time a szemétgyűjtő algoritmusok működése során azt az időt jelenti, amikor a program futása megáll vagy lelassul, hogy a garbage collector elvégezhesse a memóriakezelési feladatokat. Ilyenkor a szemétgyűjtő megkeresi és felszabadítja a már nem használt objektumokat, így több szabad memória áll rendelkezésre. Minél hosszabb a „pause time”, annál inkább észrevehető a program lassulása a felhasználók számára, ezért sok GC algoritmus célja ennek az időnek a minimalizálása a gördülékenyebb működés érdekében.
A ZGC-nél egyébként a maximális garantált pause time a milliszekundum törtrésze, így ez azokban az helyzetekben, ahol a Java-t alkalmazzák, nem jelent problémát.
Mit jelent az, hogy generational?
A Generational ZGC lényege az, hogy külön generációkat tart létre az újonnan és régen létrejött object-eknek, így a ,,fiatal” object-eket – amik a megfigyelés alapján korán szűnnek meg -, gyakrabban össze lehet gyűjteni. Ezt úgy lehet megvalósítani, hogy ha a fiatal, relatíve frissen létrejött objektumokat egy másik memóriatérben tároljuk, mint az idősebbeket. A szakirodalom egyébként ezeket a ciklusokat nevezi minor, illetve major cycle-nek.
A garbage collection kifejezetten egy olyan téma, amire szeretnek rákérdezni az interjúztatók és fontos ahhoz, hogy megértsük, mi történik a háttérben, amikor írunk egy programot, éppen ezért a tanfolyamainkon is kiemelt szerepet biztosítunk annak, hogy hallgatóink megértsék a GC alapvető szerepét és működését.
Markdown kommentek
Korábban ha a kódba akartunk kommentet írni (ezt hívjuk JavaDoc-nak), ezt kizárólag egy sajátos HTML nyelven tudtuk megcsinálni, amit ehhez hasonló Java-specifikus elemek díszítettek: {@code hashCode}. A tapasztalt szemnek teljesen érthető, hogy ez mi, de meg lehetne ezt egyszerűbben is oldani.
Éppen ezért üdítő újdonság, hogy a java 23-tól Markdown-ban is meg lehet írni ezeket a kommenteket, ami egy hangyányival egyszerűbbé, letisztultabbé és átláthatóbbá. teszi a dokumentációnkat Markdown-t egészen biztosan láttál már, akár a Hackerrank feladatai között böngészve, akár egy GitHub lévő projekten .md fájljára gondolsz.
Magáról a funkcióról itt olvashatsz többet, és itt is megragadnám az alkalmat arra, hogy ajánljam a hivatalos dokumentációt olvasgatásra, tanulásra.
Modul import deklarációk (preview)
Ennek a funkciónak a célja röviden az, hogy egy adott modul által exportált package-eket egy utasítás keretében be lehessen importálni. Ez jelentős egyszerűsítés ahhoz képest, hogy minden osztályt külön be kellett importálni úgy, hogy a package hierarchiáját ismerned kellett. A hivatalos dokumentáció, amit természetesen minden esetben javaslok elolvasásra, adott egy példát, ahol a beimportált könyvtárak jelentősen hosszabbá teszik a kódunkat:
import java.util.Map; // or import java.util.*;
import java.util.function.Function; // or import java.util.function.*;
import java.util.stream.Collectors; // or import java.util.stream.*;
import java.util.stream.Stream; // (can be removed)
String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m =
Stream.of(fruits)
.collect(Collectors.toMap(s -> s.toUpperCase().substring(0,1),
Function.identity()));
És valóban, egy viszonylag egyszerű, pár soros kód esetén is 4 db importunk van, ami majdnem olyan hosszú, mint maga a megírt kódunk. A megoldás az import module statement lesz, ami a következőképpen fog kinézni ebben a konkrét esetben:
import module java.base;
String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m =
Stream.of(fruits)
.collect(Collectors.toMap(s -> s.toUpperCase().substring(0,1),
Function.identity()));
Tömörebb, egyszerűbb, viszont egy dologra figyelned kell: ha egy több modult importálsz, megtörténhet, hogy a ugyanaz az osztálynév több helyen is szerepel – például a java.base és a java.desktop modulok importálása esetén a következő sor fordítási idejű hibával fog elszállni:
import module java.base; // exports java.util, which has a public List interface
import module java.desktop; // exports java.awt, which a public List class
...
List customList = ... // Error - Ambiguous name!
...
Ennek az oka, ahogy a kommentekben is olvashatod, hogy a fordító nem fogja tudni, hogy java.util.List-et vagy a java.awt.List-et importálja-e be 🙂
Friss tudást szeretnél?
Azért vagyunk, hogy segítsünk.
Ki szeretnéd próbálni az import module-t? Hajrá, viszont emlékezz rá, hogy ez egy preview feature, így alapértelmezetten nem elérhető a Java 23-ban, külön engedélyezni kell. Arról, hogy ezt hogy tudod megtenni, itt olvashatsz részletesen.
Amennyiben új vagy a Java-ban, és érdekel a nyelv, javasoljuk, hogy kezdd el nézni ingyenesen elérhető YouTube videósorozatunkat! A sorozat első részét lent is megtekintheted:
Köszönöm, hogy velünk tartottál, várunk sorozatunk következő részénél!
Szerző: Nagy Csongor