fbpx

Java 10 újdonságai – 1. rész

Máris itt a Java 10?

Java 10
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:

  1. Local-Variable Type Inference
  2. Consolidate the JDK Forest into a Single Repository
  3. Garbage-Collector Interface
  4. Parallel Full GC for G1
  5. Application Class-Data Sharing
  6. Thread-Local Handshakes
  7. Remove the Native-Header Generation Tool (javah)
  8. Additional Unicode Language-Tag Extensions
  9. Heap Allocation on Alternative Memory Devices
  10. Experimental Java-Based JIT Compiler
  11. Root Certificates
  12. 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<>();

Java 10 - szóhoz se lehet jutni, akkora a fejlődés

É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. 🙂

Ha tetszett, oszd meg!