Autoboxing and unboxing in Java
Auto Pack
This is an automatic encapsulation of a primitive type in its equivalent wrapper class whenever an object of this type is required. There is a great article from ffriend about encapsulation and other OOP principles . Autoboxing occurs:
- When assigning a primitive type value to a variable of the corresponding wrapper class.
- When passing a primitive type to a parameter of a method that expects its corresponding wrapper class.
Examples
Up to JDK 5
public class Main {
public static void main(String[] args) {
Integer iOb = new Integer(7);
Double dOb = new Double(7.0);
Character cOb = new Character('a');
Boolean bOb = new Boolean(true);
method(new Integer(7));
}
public static void method(Integer iOb) {
System.out.println("Integer");
}
}
Starting with JDK 5
public class Main {
public static void main(String[] args) {
Integer iOb = 7;
Double dOb = 7.0;
Character cOb = 'a';
Boolean bOb = true;
method(7);
}
public static void method(Integer iOb) {
System.out.println("Integer");
}
}
Auto Unpack
This is a conversion of a wrapper class to its corresponding primitive type. If the wrapper class was null when unpacking , a java.lang.NullPointerException will be thrown .
Unboxing happens:
- When assigning an instance of a wrapper class to a variable of the corresponding primitive type.
- In expressions in which one or both arguments are instances of wrapper classes (except for the operation == and! =).
- When passing an object of a wrapper class to a method that expects an appropriate primitive type.
Let's take a closer look.
1. Upon assignment
Up to JDK 5
int i = iOb.intValue();
double d = dOb.doubleValue();
char c = cOb.charValue();
boolean b = bOb.booleanValue();
Starting with JDK 5
int i = iOb;
double d = dOb;
char c = cOb;
boolean b = bOb;
2. In expressions
Since arithmetic and comparison operators (exception == and! =) Apply only to primitive types, we had to manually unpack them, which significantly reduced the readability of expressions, making them bulky, and the code as a whole.
Integer iOb1 = new Integer(5);
Integer iOb2 = new Integer(7);
System.out.println(iOb1.intValue() > iOb2.intValue());Thanks to auto-unpacking, we can safely write expressions without using conversion methods. Now the Java compiler is following this.
System.out.println(iOb1 > iOb2);
System.out.println(iOb1 + iOb2);When comparing wrapper classes with the == or! = Operator, comparisons are made by reference rather than by value, and confusion can occur. For example, what do you think will be displayed when the following code is executed?
Integer iOb1 = 100;
Integer iOb2 = 100;
System.out.println(iOb1 == iOb2);
Integer iOb3 = new Integer(120);
Integer iOb4 = new Integer(120);
System.out.println(iOb3 == iOb4);
Integer iOb5 = 200;
Integer iOb6 = 200;
System.out.println(iOb5 == iOb6);Answer: in the first case - true, in the second and third - false.
In the first case, the static method java.lang.Integer.valueOf (int) is actually called, which caches values from -128 to 127 (the upper limit can be changed) and, when reused, removes them from the so-called pool (a set of initialized and ready-to-use objects) ) In the second, objects are created explicitly, therefore they have different references.
3. When passed to a method
public class Main {
public static void main(String[] args) {
Integer iOb = 10;
method(iOb);
}
public static void method(int i) {
System.out.println("int");
}
}
An int will be displayed, but it is worth noting that if overload with the corresponding wrapper class is implemented for a method, it will be called.
public class Main {
public static void main(String[] args) {
Integer iOb = 10;
method(iOb);
}
public static void method(int i) {
System.out.println("int");
}
public static void method(Integer iOb) { //Будет вызван данный метод
System.out.println("Integer");
}
}
It should also be remembered that autopacking and autopacking do not work for arrays.
public class Main {
public static void main(String[] args) {
Integer[] iObs = new Integer[] {5, 10, 50, 2, 7};
method(iObs); //Ошибка компиляции
}
public static void method(int ... i) {
System.out.println("int[]");
}
}
Poor performance
Wrapper classes are immutable, so each auto-packaging (except for values from pool) creates a new object, which can lead to unreasonable memory consumption.
public static Integer sumBeforeInclusive(Integer number) {
Integer iOb = number;
if (number > 1) iOb += sumBeforeInclusive(number - 1);
return iOb;
}
Primitive types and their wrapper classes
- byte - Byte
- short - Short
- int - Integer
- long - Long
- float - float
- double - Double
- char - Character
- boolean - boolean