Máris itt a Java 10?

Nemrég történt, hogy a Java 9 újításai, a Project Jigsaw eredményeképp megvalósult modularizáció és társai napvilágot láttak, egészen pontosan 2017. szeptember 21-én. Előtte a Java 8 hivatalos megjelenése 2014. március 18-án volt, vagyis 3,5 év telt el a kettő között. A Java 10 pedig most egy hete 2018. március 20-án jelent meg, vagyis egy röpke fél év után.
Az Oracle – a Java gondnoka – új kiadási ütemezést tervezett meg, amelynek első alanya a Java 10. A terv, hogy félévente új főverzióját köszönthetjük a Java-nak, ami elősegíti mind a szoftverfejlesztő cégeknek, mind a programozóknak a könnyebb adaptálódást.
Mi a 12 újdonság a Java 10-ben?
Fél év alatt 12 JEP (Java Enhancement Proposal) készült el és került bele a 10-es verzióba:
- Local-Variable Type Inference
- Consolidate the JDK Forest into a Single Repository
- Garbage-Collector Interface
- Parallel Full GC for G1
- Application Class-Data Sharing
- Thread-Local Handshakes
- Remove the Native-Header Generation Tool (javah)
- Additional Unicode Language-Tag Extensions
- Heap Allocation on Alternative Memory Devices
- Experimental Java-Based JIT Compiler
- Root Certificates
- Time-Based Release Versioning
Az elkövetkezendő blog poszt sorozatban ezekről az új feature-ökről olvashatsz. Kezdjük az elején!
Helyi változó típuskikövetkeztetés
A beszédes Java
A Java mindig is híres volt arról, hogy kicsit bőbeszédű (sok a boilerplate kód). Az A&K Akadémia Java tanfolyamain is látom a tanulók arcán a csodálkozást, hogy miért kell mindent többször leírni. Gondolj csak egy egyszerű lista példányosításra:
List<String> list = new ArrayList<String>();
A Java 7 segített először nekünk, mert bevezette a diamond operátort, és a típusparamétereket legalább nem kellett kétszer leírni:
List<String> list = new ArrayList<>();
És aztán 2 427 nappal később most a Java 10-ben:
var list = new ArrayList<String>();
Most már legalább a változó típusát nem kell kiírnunk, hanem használhatjuk a var szót.
Szándékosan nem írtam azt, hogy kulcsszót, mert a var a klasszikus értelemben nem egy új kulcsszó, mint mondjuk az int meg a super. A var nem kulcsszó, hanem foglalt típusnév. Épp ezért ha eddig használtad a var-t, mint helyi változónevet valamelyik projektedben, akkor ez nem fog most sem fordítási hibát okozni.
Ez teljesen rendben van:
var var = "Hello and welcome Java 10!";
Az, hogy a var foglalt típusnév, ez azt is jelenti, hogy csak olyan helyeken használható, ahol a Java fordító egy típusnevet vár.
Szép dolog ez a típuskikövetkeztetés, de hogy is működik pontosan?
Mi lesz a list változóm típusa, ha azt így definiálom?
var list = new ArrayList<String>();
A Java mérnökei a KISS elvet alkalmazták (Keep it simple, stupid) és a Java fordítót egy egyszerű, de hatásos kikövetkeztetési stratégiával áldtak meg:
Épp egy ArrayList-et példányosítasz a new operátorral? Akkor ez ArrayList típusú változó lesz.
Nyilván ez nem a leg high tech-ebb megoldás, de megteszi.
Lehetett volna kidolgozni egy eljárást, ami hogyha találkozik egy var változó definícióval, akkor onnantól kezdve átvizsgálja a kódot és megnézi, hogy ha az egy referencia típus, akkor a referencián keresztül az objektum milyen tagjait éri el a kód és ezek alapján a példányosított objektum típusából kiindulva megnézné, hogy az osztályhierarchián feleleve gyalogolva melyik az a típus, ami még eleget tesz az elemzésnek, és ezt a típust választhatná a változó típusának.
Ez elég komplex lett volna és egy olyan problémát okozott volna, amit nagyon nem szeretünk. Ez pedig az, hogy ha módosítjuk a kódunkat a 342. sorban, akkor ne romoljon el a 174.-ben.
Ezt a jelenséget action at a distance-nek hívjuk, és egy ellenminta (anti-pattern), vagyis kerülendő.
De az, hogy a Java-t fejlesztő mérnökök a típuskikövetkeztetésre az egyszerűbb módszert választották ez igazából teljesen érthető. A var csak helyi változókra működik. Nem használható se paraméter változónál, se mező szintű változónál. A helyi változók hatóköre pedig a legkisebb, itt a legelfogadhatóbb az, ha egy ArrayList-re nem List interfész típusú referenciával hivatkozunk. A helyi változók pusztán konkrét metódusok implementációs részletei.
Amit a var-ral nyer(het)ünk az pedig az olvashatóság. A programozói munka során sokkal többet olvassuk a kódot, mint írjuk. Ha az agyunknak nem kell ezt a plusz terhet elviselnie, hogy még a helyi változóknál is a referencia típusát feldolgozza, akkor több agyi kapacitásunk marad a többi, lényegesebb dologra, például hogy megértsük az üzleti logikát.
Ami még szintén jó hír, hogy a var igazából nem más, mint egy szintaktikai édesítőszer (syntactic sugar). A forráskód lefordítása során a var-os kifejezéseket a fordító helyettesíti a kikövetkeztetett típussal, tehát ebből
var list = new ArrayList<String>();
ez lesz:
ArrayList<String> list = new ArrayList<String>();
Így nem kell azon annyira aggódnunk, hogy egy új nyelvi feature használatával újabb, eddig nem ismert hibákat okozunk kódunkban.
Van var de nincs val. Miért?
Más programozási nyelvekben tipikusan a var és val is elérhető. Ez utóbbi a variable és a final szavak összevonásából keletkezett. A JEP fejlesztéseknél a közösség visszajelzéseit is mindig figyelembe veszik és a val esetén nem volt annyira szignifikáns a különbség, hogy bevezessék új nyelvi elemként. A döntést azzal is magyarázták, hogy még a helyi változók esetén a legkevésbé fontos a változó módosíthatatlansága, illetve a Java 8-ban bevezetett effectively final koncepció ezt már valamilyen szinten kezeli. Ha szeretnénk, akkor persze a var definíciónkat tehetjük final-lá ily módon:
final var list = new ArrayList<String>();
Mostantól minden helyi változót írjak var-ral?
Semmiképp. Mint minden nyelvi elem, ez is csak egy eszközt ad a kezünkbe, amivel tudunk jobb kódot írni. De akármennyire is szép és jó eszközök vannak a kezünkben, mindig megtalálhatjuk (és meg is találjuk) a módját annak, hogy lábon lőjük magunkat.
A var-nál sincs ez másként. Fontos, hogy mindig megfontold, hogy a kód, amit a segítségével írtál, az olvashatóbb lett-e. Gondolj bele miután megírtad a kódod, hogy mit szólna hozzá egy másik programozó, aki most került a projektedre és most találkozik ezzel a kódrészlettel először. Könnyíteni vagy nehezítené számára a kódolvasást?
To var or not to var?
A var, mint új nyelvi elem, egy olyan újdonság, amivel minden Java programozó találkozni fog. A megfelelő helyzetekben alkalmazva növelheti a kód olvashatóságát és ekkor érdemes használni. Csak helyi változóknál használható. De a var ellenére a Java továbbra is erősen típus nyelv maradt. Az út, amely az egyre könnyebben olvasható kód írásához vezet még hosszú, de a Java 7-ben a diamond operátor és most a Java 10-ben a var mérföldköveknek számítanak rajta. Így hát befejezésként azt mondhatom, hogy
Congratulations! You are being rescued! Please do not resist. 🙂