tifyty

pure Java, what else ?

Auto boxing

Az autoboxing-gal minden Java fejlesztő tisztában van, amióta van 1.5 Java. (Vagy én vagyok nagyon naiv. Ha a matchbox jutott eszedbe, vagy hirtelen box kesztyűket húzó, és boxoló autókra asszociáltál, akkor vagy nem Java fejlesztő vagy, vagy ideje átismételni.) Van is róla jó kis tutorial az ORACLE oldalain. Az autoboxing az, amikor a Java fordító olyan kódot generál, amelyik valamelyik primitív típusból objektumot állít elő automatikusan, amikor arra van szükség. Tehát írhatjuk, hogy

Integer a = 42;

és ebből automatikusan generálódik egy olyan értékadás, ami az int 42 értéket Integer objektummá teszi. És ez annyira szép, és egyszerű, és annyira belefeledkezünk az évek során, hogy egyszer csak senior fejjel is rácsodálkozunk egyes részletekre, és egy ideig nem értjük.

Például azt, hogy van double.class és Double.class. Ugye mind a kettő egy objektum (mint minden osztály) és mind a kettő típusa Class. Sőt! Java 1.5 óta mind a kettő típusa Class<Double>.

No de, ha ugyanaz a típusuk, akkor kompatibiliseknek kellene lenniük egymással. Márpedig

public class TypeFun {
    public static void main(String[] args) {
        // public static final Class<Double>   TYPE = (Class<Double>)Class.getPrimitiveClass("double");
        System.out.println("Double.TYPE == double.class: " + (Double.TYPE == double.class));
        System.out.println("Double.TYPE == Double.class: " + (Double.TYPE == Double.class));
        System.out.println("double.class.isAssignableFrom(Double.class): " + (double.class.isAssignableFrom(Double.class)));
        System.out.println("Double.class.isAssignableFrom(double.class): " + (Double.class.isAssignableFrom(double.class)));
    }
}

eredménye

Double.TYPE == double.class: true
Double.TYPE == Double.class: false
double.class.isAssignableFrom(Double.class): false
Double.class.isAssignableFrom(double.class): false

vagyis a Double primitív párja a double.class (nem meglepő), mégis az egyik a másikból nem assign-olható. (na ezt fordítsa le valaki úgy, mint az aggódások szétválasztását)

Persze utána lehet nézni a dolgoknak, hiszen a Double osztály benne van a Java RT-ben, és open source. Ott viszont azt látjuk, hogy a

public static final Class<Double>	TYPE = (Class<Double>) Class.getPrimitiveClass("double");

Miért nem double.class? Hiszen az a Double típus primitív megfelelője, és minden olyan osztályhoz, amelyiknek van primitív párja a TYPE mező a primitív párját adja vissza.

A válasz nem triviális és elég mélyen bele kell vájni a Java és a JVM lelki világába, hogy megértsük. Mivel a double nem osztály, ezért nincs is olyan igazán, hogy double.class. A Java fordító, és a run time library itt is összefonódik egy kicsit, és a fordító tudja, hogy a Double osztály definiál egy TYPE típusú konstans mezőt, amelyik a Double primitív megfelelőjének az osztálya, és valahányszor a kódban double.class-t lát valójában Double.TYPE-ot fordít. (Ezt érdemes kipróbálni és megnézni javap-pal.) Emiatt nem írhattak a RT fejlesztői sem

public static final Class<Double>	TYPE = double.class;

kódot a Double forrásába, hiszen abból

public static final Class<Double>	TYPE = TYPE;

lett volna, aminek nem lenne sok értelme. És hogyan megy az autobox-ing pontosan?

Double b = (double)1.0;

forrásból

         0: dconst_1      
         1: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
         4: astore_1 

lesz, ha viszont megfordítjuk, és kicseréljük a két d betűt

double b = (Double)1.0;

akkor

         0: dconst_1      
         1: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
         4: invokevirtual #3                  // Method java/lang/Double.doubleValue:()D
         7: dstore_1    

ami elég sok mindent megmagyaráz. A double.class és a Double.class nem assignolható egymásból, de az autoboxing ezt megoldja. Rég volt már a Java 1.4 szerencsére el is felejtettük.

Házi feladat: ismételjük át önállóan, hogy mi a helyzet az autoboxing-gal túltöltött metódus argumentumoknál!

6 responses to “Auto boxing

  1. tvk február 26, 2014 10:49 de.

    Ez az a dolog, amit ha tudnom kell akkor rossz a kód. 🙂

    • Peter Verhas február 26, 2014 10:57 de.

      Erősen függ attól, hogy mit nevezünk rossznak. De alapvetően érteni vélem, hogy mire gondolsz, és egyetértek vele.

      Akkor is érdemes tudni, amikor nagy mennyiségben akarsz primitív adatot kezelni, sok lebegőpontos, vagy egész számot, esetleg bináris adatokat. Nem biztos, hogy ilyen mélységben kell tudni, de ha mégis meg van ez az ismeret, akkor biztos nem futsz bele olyan pofonokba, hogy valahol objektumokat készítesz primitívek helyett akár hússzor több helyet foglalva a memóriában, mint kellene.

  2. Péter András Szászvári február 26, 2014 8:57 du.

    A “senior fejjel”-t én egyszerűen csak vén fejjel-re fordítottam. Auto outboxing. 🙂

  3. Kofa február 26, 2014 11:22 du.

    A JLS ide vágó szakasza: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.8.2
    The type of p.class, where p is the name of a primitive type (§4.2), is Class, where B is the type of an expression of type p after boxing conversion (§5.1.7).

    Köszönet Péternek a türelméért! 🙂

  4. Zoltán Baranyi március 5, 2014 12:55 de.

    Ez kicsit ide kívánkozik, bár pont a másik irány: http://www.javaperformancetuning.com/news/news159.shtml
    De interjúkérdést nem ér belőle csinálni 🙂

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: