tifyty

pure Java, what else ?

get(Object) miért?

Késő nyári este volt, amikor a forróság már alábbhagyott, az árnyékok is hosszabbak lettek. A birkák is felkeltek, hogy a legelőről átvonulva éjjeli szálláshelyükre menjenek, ahol az éjszakai hideget összebújva vészelhetik át. Pásztoraik nem nagyon figyeltek rájuk, arra ott voltak a kutyák, meg aztán ők is érezték, hogy jön be a hideg, hát az éjszakai karámok mellett a szokott helyen tüzet raktak, főztek, és régmúlt időkről beszélgettek.

  • Én azt nem értettem soha – kezdte a beszéd fonalát az egyikük — hogy amikor bejött a Java 1.5 verzió, akkor a kollekcióknál, például a Map interfészen miért maradt a get metódus argumentuma Object. Amikor az lehetett volna generikus. Voltak olyan hibák, amikor refaktor után ez hagyott bent hibát. Azt hittem, hogy a fordító majd mindenhol kiabálni fog, ahol nem megfelelő az argumentum típusa, de nem kiabált.

Hallgattak egy sort. Jó volt megrágni az emlékeket, és minden egyes mondatot. Itt Nepálban lassan telt az idő, nem úgy, mint régen, a mikor még programozóként naponta jöttek az új patch-ek, release-k és sprintekben loholtak a megrendelő kívánságait kielégíteni. Itt ilyen nem volt, ezért is jöttek ide. Mégis jó volt elmerengeni a régi időkön.

  • Hát én azt gondolom – mondta egy másik -, hogy azért nem jelzett a fordító hibát, mert az argumentum típusa megfelelő volt. Object. Hiszen az volt a runtime specifikációban. Ha jól emlékszem.
  • Persze, az volt! – fortyant fel az első, bár ez a felfortyanás is aludttej volt a hajdani felfortyanások forralt borához képest – De éppen azt kérdem, hogy miért volt Object? Hülyék voltak az ORACLE programozói?
  • Az akkor még SUN volt. – bökte közbe egy harmadik, de csak egy pillanatra akasztotta meg a párbeszédet, nem törődtek vele.
  • Nem voltak hülyék. Olyan szépen összetették azt a nyelvet. Még ma is a karám ajtó vezérlése Java-ban megy!

Erre néhányan elkezdtek kuncogni, mert eszükbe jutott, hogy minap a karámajtó nem akart kinyílni és ki kellett várni egy teljes garbage collection ciklust, mire ki lehetett engedni a birkákat.

  • Hát ha nem voltak hülyék, akkor bizonyára volt logikus magyarázat, és ha volt, akkor az meg van ma is. A jövő változik, a történelmet meg lehet változtatni de a tények azok makacs dolgok, azok lassan változnak. Ha nekik volt racionális okuk, akkor arra mi is rájöhetünk. – mondta a legöregebb, akit a csapat vezetőjeként viselkedett. Nem nevezték ugyan ki, de ha valamit mondott, akkor ha nem is értettek mind vele egyet többnyire, nem mindig, de kiderült, hogy neki volt igaza. Ő volt nem hivatalosan a birkanyáj architekt. – Most pedig aludjunk! Majd a kutyák vigyáznak ránk!

Ez volt mindig az utolsó szó elalvás előtt. Amikor ez elhangzott utána már nem volt több szó, csak szuszogás a híg levegőben, ahogy a tüdők próbálták az alvó testet ellátni oxigénnel.

Másnap este ismét beszélgettek a tűz körül.

  • Azt hiszem, rájöttem mi a válasz a tegnapi kérdésre. – kezdte megint a beszédet aki tegnap is.

Hümmögtek, és a birka pörkölttek foglalkoztak, amit még tegnap főztek, és közelebb húzódtak a tűzhöz. Ma nem kellett főzni, csak kicsit megmelegíteni ami tegnapról maradt, így kisebb tűz is elég volt, kevesebb fa. A fa ritka volt ilyen magasan, és ezért optimalizálni kellett az erőforrások felhasználását.

  • Szóval az van, hogy ott van a Map. Mondjuk belerakunk valamit. Ahogy a specifikáció mondja put(K key, V value), generikus típusok. Viszont nem biztos, hogy amikor ki akarom venni az értéket, akkor ugyanolyan lesz a key objektumom típusa. Lehet például a K leszármazottja. Ezért a get argumentuma Object.

Ettek egy sort, néhányan egymásra néztek, mint akik értik egymás gondolatait is, majd az egyikük megadta az aznapi választ:

  • Akkor lehetne get(Z key) ahol a Z extends K generikus. Szóval, asszem, … ezen még dolgozzá! Mi meg aludjunk, a kutyák meg…

Nem fejezte be a mondatot. Aznap éjjel az egyik volt programozó birkapásztor csak sokára aludt el.

Másnap valahogy nem ment úgy a birkaterelés, mint máskor. Sok hibát vétettek, és ezt még a kutyák is észrevették. Nekik általában nem volt sok dolguk, csak akkor, amikor a pásztorok hibáztak. Ilyenkor úgy tettek, mintha visszaterelnék a birkát a nyájhoz, de igazából a pásztor volt az akinek ki kellett javítania a hibát, ők csak jeleztek. Szorgalmas, folyamatos figyelést igénylő, unalmas munka.

Este amikor összegyűltek megint nagy lángot raktak, mert bár fogytán volt a fa, de nagy hideg volt várható, és nem akartak megfagyni. Ha olyanok az igények, akkor alá kell tenni az erőforrást, másként ez nem megy. Újabb adagot is kellett főzni, mert napközben a napra rendelt adaggal meglépett az egyik kutya, amelyik pásztornak képzelte magát.

  • Sokat gondolkodtam napközben. – kezdte megint a programozó, az a bizonyos, de a többiek erre elkezdtek kuncogni, és az egyikük közbe is vetette:
  • Ne gondolkodj Woyczek fiam, az nem tesz jót!

Ezen többen nevettek, bár többnyire nem értették, hogy miért hívta Woyczek-nek a társukat az öreg, hiszen nem az volt a neve, de mindez nem számított, nem is kérdezték meg.

  • Szóval gondolkodtam, és arra jutottam, hogy a nem generikus get meg contains definíciójában kell keresni az okot. És eszembe jutott, hogy a javadoc dokumentáció azt írta, hogy akkor ad vissza egy értéket a get ha a paramétere egyenlő az equals szerint azzal a kulccsal amivel beraktuk az értéket a map-be. És hát az equals pedig Object-et vár, nem is várhat mást, hiszen két objektum egyenlő lehet egymással akkor is, ha az osztályai közül egyik sem leszármazottja a másiknak. Nem jól gondolom?

Hümmögtek. Ez most már nem sokat számított. Olyan szavak kavarogtak a fejükben, mint javadoc, meg equals. Milyen jó volt ezeket a szavakat újra hallani. Végül megszólalt az öreg:

  • Örülök neki, hogy sikerült végiggondolnod. Remélem, hogy ezzel elégedett is leszel, és holnap kevesebb lesz a bug a terelés közben. – Ezen megint sokan kuncogtak. – Most meg aludjuk. A kutyák meg…

8 responses to “get(Object) miért?

  1. Kofa szeptember 3, 2012 11:05 de.

    “Viszont nem biztos, hogy amikor ki akarom venni az értéket, akkor ugyanolyan lesz a key objektumom típusa. Lehet például a K leszármazottja. Ezért a get argumentuma Object.” – ez nem igaz; ha
    V get(K key)
    alakú lennek, akkor K helyére tetszőleges K leszármazott behelyettesíthető, pl. a
    map.add(keySubclass, valueSubclass)
    hívás is lefordul, pedig az add signature-e K-t és V-t vár.
    Az igazi ok az, amit az equalsról írtál, és még egy: az alábbi típusú kód nem fordulna le:
    processMap(Map<? extends X, ? extends Y> map)
    A fenti metódus belsejében, ha a Map.contains és get K típust várna, nem tudnád őket használni, mert a K = ? extends X típusa ismeretlen, csak null-lal hívhatnád ezeket a metódusokat. Ez az ára annak, hogy a put (és a Collection leszármazottakban az add) biztonságos lehet: mivel ismeretlen típussal az add nem fordul le, a get/contains sem fordulna le, ha ugyanúgy lennének megszorítva.

    • v szeptember 3, 2012 11:47 de.

      Igen. Köszönöm a kiegészítést.

      • Kofa szeptember 3, 2012 12:49 du.

        Bár ha továbbgondolom, egy másik metódussal el lehet kapni a wildcardot:
        private void <L extends K, W extends V> doProcessMap(Map<L, W> map) {…}
        és
        public void processMap(Map<? extends K, ? extends V> map) {
        doProcessMap(map);
        }
        És ezzel meg is lenne oldva a probléma (teljesen generalizált kóddal is menne a get és a containsKey).

  2. GZsolt szeptember 3, 2012 4:21 du.

    Hol lehet jelentkezni tibeti birkát terelni?
    Nemsoká’ megyek szabira. Jót tenne :-))

  3. Rév Tamás szeptember 3, 2012 11:20 du.

    Én még úgy is tudom, hogy különböző típusú objektumonál lehet ugyani, hogy o1.equals(o2) true-t ad vissza (ha Class1 o1 = new Class1(); és Class2 o2 = new Class2();), csak az egy elég illetlen dolog.

    Mégpedig azért illetlenség, mert amikor a projekt eljut a maintenance fázisba (khm), akkor elég nehéz elérni, hogy o1.equals(o2) o2.equals(o1) igaz legyen. Mert mi van, ha Class1 kap egy új mezőt, és a Class1-es equalst erről értesítjük, de a Class2-eset nem?

  4. fodb szeptember 6, 2012 2:54 du.

    Szerintem gáz a get(Object). Egy Map<K>-ben minden kulcs K, get(nemK)-val le se szabadna fordulnia.

  5. Bence február 5, 2013 7:07 du.

    Ha jól tévedek, tetszőleges K -ra igaz, hogy extends Object, vagyis az equals(Object o) egy árva szót nem szólna.

    A történet 10 pontos, szívesen olvasnék még ilyeneket.

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s

%d blogger ezt kedveli: