📜 ⬆️ ⬇️

Autoboxing and unboxing in Java

Today we’ll talk about autoboxing and unboxing. This is one of the significant changes made in JDK 5. Now developers can write cleaner code, but a lack of understanding of how this mechanism works can lead to poor performance.

Autopacking


This is an automatic encapsulation of a primitive type into 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 happens:
  1. When assigning a value of a primitive type to a variable of the corresponding wrapper class.
  2. When passing a primitive type to a parameter of a method that expects a 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 at 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"); } } 

')

Autopacking


This is a conversion of a wrapper class to its corresponding primitive type. If the wrapper class is null when unpacking, a java.lang.NullPointerException will be thrown.

Unboxing occurs:
  1. When assigning an instance of a wrapper class to a variable of the corresponding primitive type.
  2. In expressions in which one or both arguments are instances of wrapper classes (except for the operation == and! =).
  3. When passing an object of a wrapper class to a method that expects the corresponding primitive type.

Let's look in more detail.

1. At assignment


Up to JDK 5
 int i = iOb.intValue(); double d = dOb.doubleValue(); char c = cOb.charValue(); boolean b = bOb.booleanValue(); 

Starting at JDK 5
 int i = iOb; double d = dOb; char c = cOb; boolean b = bOb; 

2. In terms of


Since arithmetic and comparison operators (the exception == and! =) Apply only to primitive types, we had to manually decompress, which markedly reduced the readability of expressions, making them cumbersome, 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-packaging, we can safely write expressions without using conversion methods. Now this is followed by the Java compiler.
 System.out.println(iOb1 > iOb2); System.out.println(iOb1 + iOb2); 

When the wrapper classes are compared with the operator == or! =, The comparison is performed by reference, not by value, and confusion may occur. For example, what do you think will be displayed when executing the following code?
 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 it gets them from the so-called pool (a set of initialized and ready-to-use objects ). In the second, there is an explicit creation of objects, therefore they have different links.

3. When passing 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 on the screen, but it is worth noting that if the method implements an overload with the corresponding wrapper class, 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 does 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


The wrapper classes are immutable, so each time the autopack (except for the values ​​from the pool) creates a new object, this 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


Whole numbers
  • byte - byte
  • short - short
  • int - Integer
  • long - long


Floating point numbers
  • float - float
  • double - double


Characters
  • char - Character


Boolean values
  • boolean - Boolean

Source: https://habr.com/ru/post/329498/


All Articles