Saturday, September 28, 2019

Autoboxing and Unboxing in Java

The automatic conversion of primitive data types into its equivalent Wrapper type is known as boxing and opposite operation is known as unboxing.

Autoboxing and Unboxing with method overloading

In method overloading, boxing and unboxing can be performed. There are some rules for method overloading with boxing:

Widening beats boxing
Widening beats varargs
Boxing beats varargs


Widening beats boxing

class Boxing1{ 
  static void m(int i){System.out.println("int");} 
  static void m(Integer i){System.out.println("Integer");} 
 
  public static void main(String args[]){ 
   short s=30; 
   m(s); 
 } 

     
Output:int


Widening beats varargs

class Boxing2{ 
  static void m(int i, int i2){System.out.println("int int");} 
  static void m(Integer... i){System.out.println("Integer...");} 
 
  public static void main(String args[]){ 
   short s1=30,s2=40; 
   m(s1,s2); 
 } 

     

Output:int int


Boxing beats varargs
   
class Boxing3{ 
  static void m(Integer i){System.out.println("Integer");} 
  static void m(Integer... i){System.out.println("Integer...");} 
 
  public static void main(String args[]){ 
   int a=30; 
   m(a); 
 } 

     
Output:Integer


Method overloading with Widening and Boxing

class Boxing4{ 
  static void m(Long l){System.out.println("Long");} 
 
  public static void main(String args[]){ 
   int a=30; 
   m(a); 
 } 

     
Output:Compile Time Error

Compiler uses valueOf() method to convert primitive to Object and uses intValue(), doubleValue() etc to get primitive value from Object.

Read more: https://javarevisited.blogspot.com/2012/07/auto-boxing-and-unboxing-in-java-be.html#ixzz60pL8Qd1X

Unnecessary Object creation due to Autoboxing in Java

One of the dangers of autoboxing is throw away object which gets created if autoboxing occurs in a loop. Here is an example of how unnecessary object can slow down your application :

 Integer sum = 0;
 for(int i=1000; i<5000; i++){
   sum+=i;
 }

In this code sum+=i will expand as sum = sum + i and since + operator is not applicable to Integer object it will trigger unboxing of sum Integer object and then autoboxing of result which will be stored in sum which is Integer as shown below :

sum = sum.intValue() + i;
Integer sum = new Integer(result);     
   
here since the sum is Integer, it will create around 4000 unnecessary Integer object which are just throw away and if this happens on a large scale has It potential to slow down system with frequent GC for arithmetic calculation always prefer primitive over boxed primitive and look for unintentional autoboxing in Java

There is another problem as well when you compare int variable to Integer object using == operator, the Integer object is converted to a primitive value. This can throw null pointer exception if the Integer object is null, which can crash your program.



Comparing Integer object with == in Java

Why you should not compare Integer using == in Java 5Some of the JVM cache objects of some wrapper class e.g. Integer from -128 to 127 and return same object which if compare via “ ==” can return true but after this range this validity doesn't work and to make it worse this behavior is JVM dependent so better avoid this kind of check and use equals() method. e.g.

Integer i1 = 260;
Integer i2 = 260;

if (i1 == i2) {
    System.out.println("i1 and i2 is equal");
} else {
   System.out.println("i1 and i2 is not equal ");
}

Here you will most probably get "i1 and i2 is not equal " at least in my machine.
because in this case, unboxing operation is not involved. The literal 260 is boxed into two different Integer objects ( again it varies between JVM to JVM) , and then those objects are compared with ==. The result is false, as the two objects are different instances, with different memory addresses. Because both sides of the == expression contain objects, no unboxing occurs.

Integer i1 = 100;
Integer i2 = 100;

if (i1 == i2) {
    System.out.println("i1 and i2 is equal");
} else {
   System.out.println("i1 and i2 is not equal ");
}


Here, most probably you will get the text "i1 and i2 is equal".
Because int values from -127 to 127 are in a range which most JVM will like to cache so the VM actually uses the same object instance (and therefore memory address) for both i1 and i2. As a result, == returns a true result.

This is very indeterministic and only shown by example since some JVM do optimization at certain integer value and try to return same object every time but its not guaranteed or written behavior.

So best is to avoid this kind of code in post Java 1.5 and instead use equals() method to compare Integers in Java, which is more deterministic and correct.



No comments:

Post a Comment