Wrapper Classes in Java
Java is often called an object-oriented programming language, but there is one thing that makes it different from being completely object-oriented: Java has primitive data types.
Primitive data types are:
byte
short
int
long
float
double
char
booleanThese are not objects.
For example:
int age = 22;Here, age is a primitive variable, not an object.
So we can say:
Java is not considered purely object-oriented because it has primitive data types that are not objects.
But this raises an interesting question:
If Java is object-oriented, how can we represent primitive values as objects?
This is where Wrapper Classes come into the picture.
What are Wrapper Classes?
Wrapper classes are classes that provide an object representation of primitive data types.
Each primitive data type has a corresponding wrapper class.
PrimitiveWrapper ClassbyteByteshortShortintIntegerlongLongfloatFloatdoubleDoublecharCharacterbooleanBoolean
For example:
int age = 22;Here age is a primitive.
But:
Integer age = 22;Here age is an object of the Integer wrapper class.
Why do we use Primitive Data Types?
If wrapper classes give us objects, then why don’t we simply use wrapper classes everywhere?
One major reason is performance.
Primitive data types are generally more lightweight and efficient than objects.
For example:
int a = 10;
int b = 20;Here Java stores primitive values directly without requiring an object to represent each value.
Creating and working with objects involves additional memory and object-management overhead.
Therefore, when we simply need to store and perform operations on values, primitives are often more efficient.
So:
Primitives are generally preferred when we don’t need an object.
Wrapper classes become useful when Java or an API specifically requires an object.
Why Do We Need Wrapper Classes?
There are many situations in Java where we need an object instead of a primitive.
One common example is Collections.
Consider an ArrayList:
ArrayList<Integer> numbers = new ArrayList<>();We cannot write:
ArrayList<int> numbers = new ArrayList<>();because Java Collections work with objects, not primitive types.
Therefore, we use:
Integerinstead of:
intFor example:
ArrayList<Integer> numbers = new ArrayList<>();numbers.add(10);
numbers.add(20);
numbers.add(30);Here, Integer allows integer values to be represented as objects so they can be used with the collection.
Autoboxing
Now let’s understand autoboxing.
Autoboxing means Java automatically converts a primitive value into its corresponding wrapper object.
For example:
int number = 10;Integer obj = number;Here:
int → IntegerJava automatically converts the primitive int into an Integer object.
We don’t have to manually create the object.
This automatic conversion is called autoboxing.
Conceptually, Java does something similar to:
Integer obj = Integer.valueOf(number);So:
int number = 10;
Integer obj = number;is an example of autoboxing.
Unboxing
The opposite of autoboxing is called unboxing.
Unboxing means Java automatically converts a wrapper object back into its corresponding primitive type.
For example:
Integer obj = 10;int number = obj;Here:
Integer → intJava automatically converts the Integer object into an int.
This is called unboxing.
Conceptually, Java does something similar to:
int number = obj.intValue();Autoboxing and Unboxing Together
We can have both conversions in the same program.
int a = 10; // primitiveInteger b = a; // autoboxingint c = b; // unboxing
So the flow is:
Autoboxing
int ───────────────→ Integer
↑ |
| |
└───────────────────────┘
UnboxingCreating Wrapper Objects
Wrapper classes are classes, so they provide methods that we can use.
For example:
Integer number = Integer.valueOf(100);We can also use:
Integer number = 100;The second form uses autoboxing.
Get Aishu Reddy’s stories in your inbox
Join Medium for free to get updates from this writer.
For modern Java code, using valueOf() or autoboxing is preferred over explicitly creating wrapper objects using constructors.
For example, we should avoid:
Integer number = new Integer(100);because wrapper constructors such as Integer(int) are deprecated.
Prefer:
Integer number = Integer.valueOf(100);or simply:
Integer number = 100;Useful Methods in Wrapper Classes
Wrapper classes provide many useful methods.
For example, Integer provides methods for converting strings into integers.
int number = Integer.parseInt("100");Here:
String "100"
↓
Integer.parseInt()
↓
int 100This is very useful when we receive numbers as strings.
For example:
String age = "22";int number = Integer.parseInt(age);System.out.println(number + 5);
Output:
27Without parsing, "22" + 5 would result in:
225because "22" is a string.
valueOf() vs parseInt()
These two methods can sometimes be confusing.
parseInt()
Returns a primitive int.
int number = Integer.parseInt("100");valueOf()
Returns an Integer object.
Integer number = Integer.valueOf("100");So:
parseInt() → int
valueOf() → IntegerWrapper Classes Can Contain null
Primitive variables cannot normally contain null.
For example:
int age = null;This is invalid.
But an Integer can contain null:
Integer age = null;This is useful when we need to represent the absence of a value.
For example, in databases, a column might contain NULL.
A Java Integer can represent that missing value:
Integer age = null;while:
int age;cannot represent null.
Wrapper Classes and Collections
One of the most common places where wrapper classes are used is the Java Collections Framework.
For example:
List<Integer> numbers = new ArrayList<>();We use Integer instead of int.
But notice something interesting:
numbers.add(10);We are passing an int, not explicitly creating an Integer.
Java automatically performs autoboxing:
10
↓
int
↓ autoboxing
Integer
↓
List<Integer>Similarly, when we retrieve the value:
int number = numbers.get(0);Java automatically performs unboxing:
Integer
↓ unboxing
intThis is one of the reasons autoboxing and unboxing are very useful.
Wrapper Class Caching
There is another interesting concept with wrapper classes.
Java may cache certain wrapper objects, especially for commonly used values.
For example, with Integer:
Integer a = 100;
Integer b = 100;System.out.println(a == b);This will typically print:
truebecause commonly used Integer values are cached.
But:
Integer a = 200;
Integer b = 200;System.out.println(a == b);may print:
falsebecause two different objects may be created.
This is why we should not use == to compare wrapper objects when we want to compare their values.
Instead, use:
Integer a = 100;
Integer b = 100;System.out.println(a.equals(b));equals() compares the values.
This is an important point when working with wrapper classes.
The Big Picture
We can understand wrapper classes using this simple flow:
Primitive Data Types
|
| Need object representation
↓
Wrapper Classes
|
├── int → Integer
├── char → Character
├── double → Double
├── boolean → Boolean
└── ...And Java makes the conversion easy:
Primitive Wrapper
int ───── autoboxing ───→ Integer
int ←──── unboxing ───── IntegerSo the key idea is:
Wrapper classes provide object representations of primitive data types. They are especially useful when Java requires objects, such as when working with collections, and Java automatically converts between primitives and their wrapper classes through autoboxing and unboxing.



