A Wrapper Class is a class whose object wraps or contains primitive data types. When we create an object of a wrapper class, it contains a field in which we can store primitive data types. These classes are part of the java.lang package and are essential for using primitives in the Collections Framework.
Every primitive in Java has a corresponding wrapper class. Note that while most simply capitalize the first letter, int and char have unique class names.
| Primitive Type | Wrapper Class | Size (Primitive) |
|---|---|---|
| byte | Byte | 8 bits |
| short | Short | 16 bits |
| int | Integer | 32 bits |
| long | Long | 64 bits |
| float | Float | 32 bits |
| double | Double | 64 bits |
| char | Character | 16 bits |
| boolean | Boolean | 1 bit (nominal) |
Before Java 5, converting a primitive to an object was a manual, tedious process. Modern Java uses Autoboxing to handle this automatically behind the scenes.
Integer myInt = 5; // Compiler does: Integer.valueOf(5)
int x = myInt; // Compiler does: myInt.intValue()
If primitives are faster and use less memory (which they are), why use wrappers at all? There are four major reasons:
Classes like ArrayList<T> and HashMap<K,V> only accept Objects. You cannot write ArrayList<int>; you must use ArrayList<Integer>.
An int must always have a value (even if it is 0). An Integer can be null, which is vital for database interactions where a value might be missing.
Wrapper classes host static methods for data conversion, such as Integer.parseInt("123") or Double.toHexString(d).
Generics work with Type Parameters that must be objects. Wrappers allow numbers to be passed as generic types.
Because of Autoboxing, it is very easy to forget that every Integer is a full object on the Heap. This can lead to massive performance degradation if used inside tight loops.
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i; // This creates billions of unnecessary Long objects!
}
Always use primitives for heavy arithmetic calculations.
To optimize performance, Java maintains an internal cache for Integer objects in the range of -128 to 127. If you create two Integers in this range, they might actually point to the same memory address.
Lesson: Always use .equals() to compare wrapper objects, never ==.
All Wrapper Classes in Java are Immutable. Once an Integer object is created with a value of 10, it cannot be changed to 11. When you do myInt++, Java is actually creating a brand-new Integer object with the value 11 and discarding the old one.
This example shows how to use Wrapper classes to convert strings from a file or user input into usable numbers safely.
Q: What is the difference between int and Integer?
A: int is a primitive type that stores a value directly on the stack. Integer is a class that stores a reference to an object on the heap. int cannot be null and is faster for math; Integer can be null and is required for Collections.
Q: Is Autoboxing efficient?
A: It is convenient but not necessarily efficient. Each boxing operation involves an object creation (unless cached), which puts pressure on the Garbage Collector.
Q: What happens if you unbox a null Integer?
A: It throws a NullPointerException at runtime. This is a very common bug in Java applications.
Wrapper Classes are the bridge that makes Java's Type System cohesive. While they add some memory overhead, they enable the powerful abstractions of the Collections Framework and provide a wealth of utility methods for data manipulation. Understand the "Integer Cache" and the cost of "Autoboxing," and you will write code that is both clean and performant.
Next: The Power of Java Generics →