Saturday, July 3, 2021

Java Tutorial: Wrapper Classes, Autoboxing and Auto-unboxing

Chapters

Java Wrapper Classes

Note: Some parts of this tutorial is going to use generics. So, an understanding of generics is required at some parts of this tutorial.

Wrapper classes are object wrappers for primitive types. These are wrapper classes in java: Boolan, Byte, Character, Float, Integer, Long, Short, Double. We use wrapper classes to wrap primitive types into object types so that, we can pass them to other objects that don't accept primitive types like List<>, ArrayList<>, etc.

ArrayList can't have primitive types as elements, we need to wrap primitive types first before ArrayList can accept them as its elements. Take a look at this example.
import java.util.ArrayList;
public class SampleClass{

  public static void main(String[]args){
    ArrayList<Integer> arrList = new ArrayList<>();
    arrList.add(1);
    
    Sytem.out.println(arrList.get(0));
  }
}
The code above will run just fine. You might say: "But you say that primitive types can't be elements of arraylist?". Well, my statement is still correct this add() method arrList.add(1); accepts Integer as argument. The primitive "1" is automatically converted to Integer.

Autoboxing

Autoboxing is the automatic conversion of primitives to their respective wrapper classes. The example above demonstrates autoboxing. Regardless, let's create another example.
public class SampleClass{

  public static void main(String[]args){
    //autoboxing
    Integer intOne = 1;
    
    //manual boxing
    Integer intTwo = Integer.valueOf(2);
  }
}
Imagine calling Integer.valueOf() everytime we assign an int primitive to Integer. Autoboxing removes the use of manual boxing if we're just assigning a primitive to its respective wrapper class. Take a look at this example.
public class SampleClass{

  public static void main(String[]args){
  
    //error: String can't be converted
    //to Integer
    //Integer intOne = "1";
    
    //If we want a String to be converted
    //to Integer then, we need to 
    //manually convert the String
    Integer intTwo = Integer.valueOf("1");
  }
}
Auto-unboxing

Auto-unboxing is the automatic conversion of wrapper classes to their respective primitive types. Take a look at this example.
public class SampleClass{

  public static void main(String[]args){
    //autoboxing
    Integer intOne = 1;
    
    //auto-unboxing
    int myInt = intOne;
    
    //manual unboxing
    //int myInt = intOne.intValue();
    
    System.out.println(myInt);
  }
}
Auto-unboxing removes the use of manual unboxing if we're just assigning a wrapper object to its respective primitive type.

Using Operators on Wrapper Classes

Now we know autoboxing and auto-unboxing, we also know the reason why we can use operators on wrapper classes. When an operator is used on wrapper classes, Wrapper classes are automatically converted to their respective primitive types first before performing the operation.

The result may be converted depending on the type of the variable where the result is stored.
public class SampleClass{

  public static void main(String[]args){
    Integer a1 = 1;
    Integer a2 = 3;
    
    //a1 and a2 are unboxed first
    //before performing the operation
    //then assign the result
    int intOne = a1 + a2;
    System.out.println(intOne);
    
    //a1 is unboxed first
    //before performing the operation
    //then assign the result
    intOne = a1 + 2;
    System.out.println(intOne);
    
    //the operation is performed
    //then the primitive result is
    //wrapped into Integer and
    //then it's assigned to a3
    Integer a3 = 1 + 4;
    System.out.println(a3);
    
    //a1 is unboxed first
    //before performing the operation
    //then the result is boxed
    //before it's assigned to a3
    a3 = a1 + 1;
    System.out.println(a3);
    
    //a1 and a2 are unboxed first
    //before performing the operation
    //then the result is boxed 
    //before it's assigned
    a3 = a1 + a2;
    System.out.println(a3);
  }
}
Now, let's create the manual box/unbox version of the example above.
public class SampleClass{

  public static void main(String[]args){
    Integer a1 = 1;
    Integer a2 = 3;
    
    int intOne = a1.intValue() + a2.intValue();
    System.out.println(intOne);
    
    intOne = a1.intValue() + 2;
    System.out.println(intOne);
    
    Integer a3 = Integer.valueOf(1 + 4);
    System.out.println(a3);
    
    a3 = Integer.valueOf(a1.intValue() + 1);
    System.out.println(a3);
    
    a3 = Integer.valueOf(a1.intValue() + a2.intValue());
    System.out.println(a3);
  }
}
When performing operation between primitive types, typecasting(Primitive Types) may happen.
public class SampleClass{

  public static void main(String[]args){
    
    //error: float can't be converted
    //to Integer
    //Integer intOne = 30.5f + 10;
    
    //valid
    Float floatOne = 30.5f + 10;
    System.out.println(floatOne);
    
    //error: int can't be converted to
    //Short
    //short st = 50;
    //Short shortOne = st + 50;
  }
}

No comments:

Post a Comment