Primitive types are not objects, but all data structures in Java (list, map, etc) are storing objects, so we need a mechanism to see all primitive values as objects.
For that, the Java API defines the for each primitive type, a wrapper class, in the package java.lang which is a class with one field and the compiler as a mechanism named auto-boxing/auto-unboxing to convert from a primitive type to the corresponding wrapper and vice-versa.
By example, to be able to type the list, we need an object type corresponding to the primitive type int
List<Integer> list = List.of(1, 2, 3);
You can do the conversion explicitly calling the static method valueOf
on the wrapper type
or implicitly if the target type is Object
Object booleanBox = Boolean.valueOf(true);
Object booleanBox = true;
System.out.println(booleanBox);
Object charBox = Character.valueOf('A');
Object charBox = 'A';
System.out.println(charBox);
Object byteBox = Byte.valueOf((byte) 12);
Object byteBox = (byte) 12;
System.out.println(byteBox);
Object shortBox = Short.valueOf((short) 712);
Object shortBox = (short) 712;
System.out.println(shortBox);
Object intBox = Integer.valueOf(100_000);
Object intBox = 100_000;
System.out.println(intBox);
Object longBox = Long.valueOf(10_000_000_000L);
Object longBox = 10_000_000_000L;
System.out.println(longBox);
Object floatBox = Float.valueOf(1.2f);
Object floatBox = 1.2f;
System.out.println(floatBox);
Object doubleBox = Double.valueOf(42.0);
Object doubleBox = 42.0;
System.out.println(doubleBox);
Because the wrapper are objects, the == will test the reference, not the value.
In fact, it's worst than that, the methods valueOf()
can use a cache,
so depending on the weather (the startup parameters of the VM),
valueOf
may return the same object for the same value or not
so you can not predict if == will returns true of false for a wrapper.
__Never use == on a wrapper, use equals() __
Object intBox1 = 8192;
Object intBox2 = 8192;
System.out.println(intBox1 == intBox2); // may return true or false ??
equals() on Float and Double works correctly with NaN, unlike the primitive types float and double.
double d = Double.NaN;
System.out.println(d == d);
Double d = Double.NaN;
System.out.println(d.equals(d));
so reusing the variable *box
defined above, we can write
boolean z = ((Boolean) booleanBox).booleanValue();
boolean z = (boolean) booleanBox;
System.out.println(z);
char c = ((Character) charBox).charValue();
char c = (char) charBox;
System.out.println(c);
byte b = ((Byte) byteBox).byteValue();
byte b = (byte) byteBox;
System.out.println(b);
short s = ((Short) shortBox).shortValue();
short s = (short) shortBox;
System.out.println(s);
int i = ((Integer) intBox).intValue();
int i = (int) intBox;
System.out.println(i);
long l = ((Long) longBox).longValue();
long l = (long) longBox;
System.out.println(l);
float f = ((Float) floatBox).floatValue();
float f = (float) floatBox;
System.out.println(f);
double d = ((Double) doubleBox).doubleValue();
double d = (double) doubleBox;
System.out.println(d);
Trying to unbox null throws a NullPointerException
Integer box = null;
int i = (int) box;
Wrapper types should only appears in between '<' and '>' because the generics of Java doesn't support primitive type inside the '<' and '>'.
So please don't use them as type of a field or a method parameter unless you have a very good reason.