Using wrapper classes in Java
Do not miss this exclusive book on Binary Tree Problems. Get it now for free.
Reading time: 30 minutes
A Wrapper class is a class whose object contains a primitive data types. We can think this as a primitive data type with an additional layer which enables it is get benefits of a custom user defined objects in Java.
Why we need Wrapper Classes?
-
Methods cannot modify data of primitive data types which have been passed an arguments. To do this, we need to use a wrapper class over the primitive data type.
-
The classes in java.util package handles only objects and hence wrapper classes help in converting primitive types to objects and hence, use the utilities
-
Data structures in the Collection framework, such as ArrayList and Vector, store only objects and not primitive types.
-
Only an object can support synchronization in multithreading.
Syntax
Consider a class named prev_class which can be a primitive datatype like int as well. To wrap it in a wrapper class, we create a new class with any valid name like new_class like:
class new_class
{
prev_class variable;
return_type some_functions()
{
...
}
}
Example of wrapping an int:
class int_wrapper
{
int data;
void set_data(int new_data)
{
data = new_data;
}
}
Following this, we can create objects and set new data like:
int_wrapper int_object();
int_object.data = 1;
int_object.set_data(2);
In-built wrapper classes
The seven classes of java.lang package are known as wrapper classes in java. The list of seven wrapper classes are given below:
- Primitive type boolean -> Wrapper class Boolean
Primitive datatype | Wrapper class |
---|---|
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
Autoboxing and Unboxing
As we know, Java automatically converts between datatypes to minimize the loss in accuracy. In this process, we have different rules for conversion of supported wrapper classes like Integer.
The two type of conversions are:
- Autoboxing
- Unboxing
Autoboxing:
Automatic conversion of primitive types to the object of their corresponding wrapper classes is known as autoboxing. For example – conversion of int to Integer, long to Long, double to Double etc.
Example:
// Java program to demonstrate Autoboxing
public class WrapperExample1{
public static void main(String args[]){
//Converting int into Integer
int a=21;
Integer i=Integer.valueOf(a);//converting int into Integer
Integer j=a;//autoboxing, now compiler will write Integer.valueOf(a) internally
System.out.println(a+" "+i+" "+j);
}
}
Output:
21 21 21
Unboxing: It is just the reverse process of autoboxing. Automatically converting an object of a wrapper class to its corresponding primitive type is known as unboxing. For example – conversion of Integer to int, Long to long, Double to double etc.
// Java program to demonstrate Unboxing
public class WrapperExample2{
public static void main(String args[]){
//Converting Integer to int
Integer a=new Integer(5);
int i=a.intValue();//converting Integer to int
int j=a;//unboxing, now compiler will write a.intValue() internally
System.out.println(a+" "+i+" "+j);
}
}
Output:
5 5 5
Implemetation
Following implementation demonstrates autoboxing and unboxing:
// Java program to demonstrate Wrapping and UnWrapping
// in Java Classes
class AutoBoxingUnBoxing
{
public static void main(String args[])
{
// byte data type
byte a = 1;
// wrapping around Byte object
Byte byteobj = new Byte(a);
// int data type
int b = 11;
//wrapping around Integer object
Integer intobj = new Integer(b);
// float data type
float c = 11.6f;
// wrapping around Float object
Float floatobj = new Float(c);
// double data type
double d = 251.5;
// Wrapping around Double object
Double doubleobj = new Double(d);
// char data type
char e='a';
// wrapping around Character object
Character charobj=e;
// printing the values from objects
System.out.println("Values of Wrapper objects (printing as objects)");
System.out.println("Byte object byteobj: " + byteobj);
System.out.println("Integer object intobj: " + intobj);
System.out.println("Float object floatobj: " + floatobj);
System.out.println("Double object doubleobj: " + doubleobj);
System.out.println("Character object charobj: " + charobj);
// objects to data types (retrieving data types from objects)
// unwrapping objects to primitive data types
byte bv = byteobj;
int iv = intobj;
float fv = floatobj;
double dv = doubleobj;
char cv = charobj;
// printing the values from data types
System.out.println("Unwrapped values (printing as data types)");
System.out.println("byte value, bv: " + bv);
System.out.println("int value, iv: " + iv);
System.out.println("float value, fv: " + fv);
System.out.println("double value, dv: " + dv);
System.out.println("char value, cv: " + cv);
}
}
Output:
Values of Wrapper objects (printing as objects)
Byte object byteobj: 1
Integer object intobj: 11
Float object floatobj: 11.6
Double object doubleobj: 251.5
Character object charobj: a
Unwrapped values (printing as data types)
byte value, bv: 1
int value, iv: 11
float value, fv: 11.6
double value, dv: 251.5
char value, cv: a
Using with Collection Objects
Sometimes you must use wrapper classes, for example when working with Collection objects, such as ArrayList, where primitive types cannot be used (the list can only store objects):
Example:
ArrayList<int> myNumbers = new ArrayList<int>(); // Invalid
ArrayList<Integer> myNumbers = new ArrayList<Integer>(); // Valid
Utility Methods of Wrapper Classes
Since you're now working with objects, you can use certain methods to get information about the specific object.
For example, the following methods are used to get the value associated with the corresponding wrapper object: intValue(), byteValue(), shortValue(), longValue(), floatValue(), doubleValue(), charValue(), booleanValue().
This example will output the same result as the example above:
public class MyClass
{
public static void main(String[] args)
{
Integer myInt = 5;
Double myDouble = 5.99;
Character myChar = 'A';
System.out.println(myInt.intValue());
System.out.println(myDouble.doubleValue());
System.out.println(myChar.charValue());
}
}
Another useful method is the toString() method, which is used to convert wrapper objects to strings.
In the following example, we convert an Integer to a String, and use the length() method of the String class to output the length of the "string":
public class MyClass
{
public static void main(String[] args)
{
Integer myInt = 100;
String myString = myInt.toString();
System.out.println(myString.length());
}
}
Primitive Wrapper Classes are Immutable in Java
Consider below Java program.
// Java program to demonstrate that prmitive
// wrapper classes are immutable
class Wrapper
{
public static void main(String[] args)
{
Integer i = new Integer(14);
System.out.println(i);
modify(i);
System.out.println(i);
}
private static void modify(Integer i)
{
i = i + 1;
}
}
Output:
14
14
The parameter i is reference in modify and refers to same object as i in main(), but changes made to i are not reflected in main(), why?
Explanation:
All primitive wrapper classes (Integer, Byte, Long, Float, Double, Character, Boolean and Short) are immutable in Java, so operations like addition and subtraction create a new object and not modify the old.
The below line of code in the modify method is operating on wrapper class Integer, not an int
i = i + 1;
It does the following:
- Unwrapping i to an int value
- Add 1 to that value
- Wrapping the result into another Integer object
- Assign the resulting Integer to i
Since object references are passed by value, the action taken in the modify method does not change i that was used as an argument in the call to modify. Thus the main routine still prints 14 after the method returns.
Comparison of Autoboxed Integer objects
When we assign an integer value to an Integer object, the value is autoboxed into an Integer object. For example the statement “Integer x = 1” creates an object ‘x’ with value 1.
Following are some interesting output questions based on comparison of Autoboxed Integer objects.
Predict the output of following Java Program
public class Main
{
public static void main(String args[])
{
Integer x = 200, y = 200;
if (x == y)
System.out.println("Equal");
else
System.out.println("Not Equal");
}
}
Output:
Not Equal
Since x and y refer to different objects, we get the output as “Not Equal”
The output of following program is a surprise from Java.
public class Main
{
public static void main(String args[])
{
Integer x = 4, y = 4;
if (x == y)
System.out.println("Equal");
else
System.out.println("Not Equal");
}
}
Output:
Equal
In Java, values from -128 to 127 are cached, so the same objects are returned. The implementation of valueOf() uses cached objects if the value is between -128 to 127.
If we explicitly create Integer objects using new operator, we get the output as “Not Same”. See the following Java program. In the following program, valueOf() is not used.
public class Main
{
public static void main(String args[])
{
Integer x = new Integer(4), y = new Integer(4);
if (x == y)
System.out.println("Equal");
else
System.out.println("Not Equal");
}
}
Output:
Not Equal
Predict the output of the following program.
Public class Main
{
public static void main(String[] args)
{
Integer X = new Integer(1);
Integer Y = 1;
// Due to auto-boxing, a new Wrapper object
// is created which is pointed by Y
System.out.println(X == Y);
}
}
Output:
false
Explanation: Two objects will be created here. First object which is pointed by X due to calling of new operator and second object will be created because of Auto-boxing.
Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.