简体   繁体   中英

Casting a primitive vs Creating a object of the primitive

I'm not habitual to casting a primitive data type to an object. Saw some code like:

public static int CompareAges(Person p1, Person p2) {
    Integer age1 = p1.getAge();
    return age1.compareTo(p2.getAge());
}

The instantiation of age1 seemed extraneous, so I tried to write the code as:

public static int CompareAges(Person p1, Person p2) {
    return p1.getAge().compareTo(p2.getAge());
}

But that raised a compiler error because p1.getAge() is a primitive data type int and not an Integer , which is an object.

Intuitively, I did:

public static int CompareAges(Person p1, Person p2) {
    return ((Integer) p1.getAge()).compareTo(p2.getAge());
}

and it worked!

The question: What did I miss? Since when did we start casting primitives as value types ?

It's what happens internally:

1. Integer age1 = p1.getAge();
       Integer != int
       Integer = Integer.valueOf(int)
   Integer age1 = Integer.valueOf(p1.getAge());

2. p1.getAge().compareTo(p2.getAge());
       int.compareTo(int)
       ^^^
       // it's just a primitive type, as a result - the compile error

3. ((Integer) p1.getAge()).compareTo(p2.getAge())
       Integer.compareTo(int)
       Integer.compareTo(Integer.valueOf(int))
   ((Integer) p1.getAge()).compareTo(Integer.valueOf(p2.getAge()))

4. (Integer) p1.getAge() ---> Integer.valueOf(p1.getAge()) 
       // why so? look at callOfCode's answer

But, in my opinion, ((Integer) p1.getAge()).compareTo(p2.getAge()) looks ugly.

I would replace it to

p1.getAge() > p2.getAge() ? 1 : (p1.getAge() < p2.getAge() ? -1 : 0)

or to

Integer.compare(p1.getAge(), p2.getAge()) // java 7+

I wouldn't like to do casting in this case.


More about "autoboxing/unboxing" you may find here .

Each primitive has its own boxing type

在此输入图像描述

The Boxing could be implicit (Autoboxing) or explicit like you did it in your code.

p2.getAge() is an Example of AutoBoxing or Implicit Boxing. The method compareTo takes an Object. As it is a primitive, Java converts it automatically to the correspondent Boxing Object (Integer). You did the explicit Boxing with the cast (Integer) p1.getAge()

Difference between new Integer(primitive); and Integer integer = (Integer)primitive; Is only on bytecode level. In the first case, new object of Integer class is created in memory. In the second case, Integer.valueOf(primitive) is called internally. This is the static method that checks if primitive falls into range of -128 to 127 and if it falls, it returns value from integer cache and no new object is being created. If it not falls into that range, new Integer object is instantiated. It is used for efficiency. But such efficiency is unsignificant novadays.

int z = 1;
Integer a = (Integer)z;
Integer b = (Integer)z;
//Prints true, since Integer object is retrieved from cache (range of -128 to 127)
System.out.println(a == b);

int w = 999;
Integer c = (Integer)w;
Integer d = (Integer)w;
//Prints false, since 999 is not in cache, new Integer objects are instantiated and they points to different places in memory
System.out.println(c == d);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM