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?
Casting between primitive types enables you to convert the value of one type to another primitive type. This most commonly occurs with the numeric types. But one primitive type can never be used in a cast. Boolean values must be either true or false and cannot be used in a casting operation.
Primitive values are immutable — they cannot be changed after being created. Object references, however, are mutable and can be changed. Since objects are stored as references, special care must be taken when duplicating objects and when performing equality checks on objects.
One major difference from the explanation above is, default values of the primitive types depend on type like int is 0, char is \u0000, boolean is false, etc but the default value for wrapper classes of all types is null since they are objects.
Casting a variable to a data type basically is telling the compiler "Trust me, I know what I'm doing." In the case of casting an "Object" to "Book", you are assuring the compiler that the object is, in fact, a Book and to proceed accordingly. It also as the effect of forcing you to believe you know what you are doing.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With