Autoboxing & Unboxing

Today I’m going to discuss quite an interesting topic of autoboxing and unboxing in Java. Let’s remind what it is exactly.

Autoboxing – automatic conversion of primitive type to corresponding object wrapped class in Java.

Unboxing – automated conversion of wrapped class to corresponding primitive type.

Primitive TypeWrapper Class
booleanBoolean
byteByte
charCharacter
floatFloat
intInteger
longLong
shortShort
doubleDouble
nullnull

In the example below, we can see examples of autoboxing and unboxing at the same time.

public class Test{
  public static void main(String[] args){
    Integer a = 12; //autoboxing
    int b = a; //unboxing
  }
}

Let’s compile it

javac Test.java

and disassemble to see what is under the hood there

javap -c Test.class
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: bipush        12
       2: invokestatic  #7                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       5: astore_1
       6: aload_1
       7: invokevirtual #13                 // Method java/lang/Integer.intValue:()I
      10: istore_2
      11: return
}

So, the compiler just transformed previous example into this form

public class Test{
  public static void main(String[] args){
    Integer a = Integer.valueOf(12);
    int b = a.intValue();
  }
}

The same rule applies for all other types

AutoboxingUnboxing
Boolean Boolean.valueOf(boolean val)boolean Boolean.booleanValue()
Byte Byte.valueOf(byte val)byte Byte.byteValue()
Character Character.valueOf(char val)char Character.charValue()
Float Float.valueOf(float val)float Float.floatValue()
Integer Integer.valueOf(int val)int Integer.intValue()
Long Long.valueOf(long val)long Long.longValue()
Short Short.valueOf(short val)short Short.shortValue()
Double Double.valueOf(double val)double Double.doubleValue()

Pretty easy – you can say and would be right, but let me ask you some questions.

Q: In the code below for the section a == b will it Autoboxing or Unboxing?

public class Test{
  public static void main(String[] args){
    Boolean a = true;
    boolean b = false;
   
    boolean c = a == b;
  }
}

A: Unboxing is the right answer.

Disassembled code as proof below

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: invokestatic  #7                  // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
       4: astore_1
       5: iconst_0
       6: istore_2
       7: iload_2
       8: aload_1
       9: invokevirtual #13                 // Method java/lang/Boolean.booleanValue:()Z
      12: if_icmpne     19
      15: iconst_1
      16: goto          20
      19: iconst_0
      20: istore_3
      21: return
}

Now, when we covered previous example this question should be easy for you.

Q: What value will be assigned to variable b in the code below?

public class Test{
  public static void main(String[] args){
    Boolean a = null;
    boolean b = a;
  }
}

A: no value will be assigned to b due to exception during execution.

Exception in thread "main" java.lang.NullPointerException
	at Test.main(Test.java:4)

Code in the question is equal to this one

public class Test{
  public static void main(String[] args){
    Boolean a = null;
    boolean b = a.booleanValue(); //null.booleanValue()
  }
}

Q: What value will be assigned to variable c in the example below?

public class Test{
  public static void main(String[] args){
    Long a = 20L;
    long b = 20;
    boolean c = a.equals(b);
  }
}

A: the correct answer – true.

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc2_w        #7                  // long 20l
       3: invokestatic  #9                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
       6: astore_1
       7: ldc2_w        #7                  // long 20l
      10: lstore_2
      11: aload_1
      12: lload_2
      13: invokestatic  #9                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      16: invokevirtual #15                 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
      19: istore        4
      21: return
}

which is the same as

public class Test{
  public static void main(String[] args){
    Long a = 20L;
    long b = 20;
    boolean c = a.equals(Long.valueOf(b));
  }
}

Q: What value will be assigned to variable c in the example below?

public class Test{
  public static void main(String[] args){
    Long a = 20L;
    boolean c = a.equals(20);
  }
}

A: the correct answer – false.

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc2_w        #7                  // long 20l
       3: invokestatic  #9                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
       6: astore_1
       7: aload_1
       8: bipush        20
      10: invokestatic  #15                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      13: invokevirtual #20                 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
      16: istore_2
      17: return
}

In this example there is no type reference so 20 is represented as most appropriate integer type.

public class Test{
  public static void main(String[] args){
    Long a = 20L;
    boolean c = a.equals(Integer.valueOf(20));
  }
}

So, even if autoboxing/unboxing logic seems pretty straightforward and easy you still need to keep attention to details. As best practice to avoid memory and/or performance-related issues you shouldn’t rely on the autoboxing/unboxing mechanism in your code. The most appropriate case when this mechanism is really needed is when you store primitive types in the collection.

Photo by Ante Hamersmit on Unsplash

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.