Java Wrapper Classes
1. What Are Wrapper Classes?
Wrapper classes in Java are object representations of primitive data types. Each primitive type (like int, char, boolean) has a corresponding class in the java.lang package that wraps it into an object.
2. Why Use Wrapper Classes?
- To use primitives in object-based APIs (e.g., Collections)
- To access utility methods (e.g., Integer.parseInt())
- To allow null assignment (not possible with primitive types)
- Required for generics, as generics only work with objects
3. Types of Wrapper Classes in Java
In Java, every primitive data type has a corresponding wrapper class in the java.lang package. These wrapper classes allow you to treat primitive values as objects, enabling their use in object-oriented features such as:
- Collections (like ArrayList)
- Generics
- Method arguments requiring objects
- Use of utility methods (like parse, valueOf, compareTo, etc.)
Explanation of Each Wrapper Class
A. Integer (for int)
- Represents a 32-bit signed integer.
- Contains methods like parseInt(), valueOf(), intValue(), etc.
Integer i = Integer.valueOf(10);
int x = i.intValue(); // unboxing
B. Double (for double)
- Represents a 64-bit double-precision floating point.
- Methods: parseDouble(), doubleValue(), isNaN(), etc.
Double d = Double.valueOf(23.5);
double x = d.doubleValue();
C. Character (for char)
- Represents a single 16-bit Unicode character.
- Methods: isLetter(), isDigit(), toLowerCase(), etc.
Character ch = Character.valueOf('A');
if (Character.isUpperCase(ch)) {
System.out.println("Uppercase letter");
}
D. Boolean (for boolean)
- Represents one of two values: true or false.
- Methods: parseBoolean(), booleanValue(), etc.
Boolean flag = Boolean.valueOf("true");
if (flag) {
System.out.println("Flag is true");
}
E. Float (for float)
- Represents a 32-bit single-precision floating point.
- Similar methods to Double.
Float f = Float.valueOf(12.3f);
float result = f.floatValue();
F. Long (for long)
- Represents a 64-bit signed integer.
- Methods: valueOf(), longValue(), parseLong(), etc.
Long l = Long.valueOf(100000L);
System.out.println(l.longValue());
G. Short (for short)
- Represents a 16-bit signed integer.
- Less commonly used but useful in type conversion and memory-sensitive applications.
Short s = Short.valueOf((short) 100);
System.out.println(s.shortValue());
H. Byte (for byte)
- Represents an 8-bit signed integer.
- Typically used in I/O operations and low-level programming.
Byte b = Byte.valueOf((byte) 10);
System.out.println(b.byteValue());
5. How to Create Wrapper Objects
In Java, wrapper classes like Integer, Double, Boolean, etc., are used to create object representations of primitive values. There are two main ways to create wrapper objects:
a. Using Constructors (Deprecated since Java 9)
Integer num1 = new Integer(10);
Explanation:
- This explicitly creates a new Integer object on the heap.
- Even if an identical value exists in memory, this constructor will always create a new object.
- This approach is considered less efficient because it does not take advantage of internal caching.
Deprecation:
- Java 9 deprecated the use of wrapper class constructors.
- Using new Integer(), new Double(), etc., now shows a compiler warning.
- The Java development team recommends using the valueOf() method instead.
b. Using Factory Method – valueOf()
Integer num2 = Integer.valueOf(10);
Explanation:
- The valueOf() method is a static factory method provided by all wrapper classes.
- It returns a cached object if the value is within a certain range.
- For Integer, this range is from -128 to 127.
- For values outside this range, a new object is created.
Advantages of valueOf():
- Memory efficient – avoids unnecessary object creation.
- Supports caching for common values.
- Recommended by Java documentation.
Internal Behavior of valueOf() (for Integer):
Integer x = Integer.valueOf(100); // From cache
Integer y = Integer.valueOf(100);
System.out.println(x == y); // true (same object)
Integer a = Integer.valueOf(200); // New object
Integer b = Integer.valueOf(200);
System.out.println(a == b); // false (different objects)
6. Autoboxing in Java

Definition:
Autoboxing is the automatic conversion performed by the Java compiler when a primitive data type is assigned to a variable of its corresponding wrapper class.
In simple terms, Java wraps a primitive value into its object equivalent without requiring explicit code to do so.
Example:
int a = 5;
Integer obj = a; // Autoboxing
Explanation:
- a is a primitive type (int).
- obj is an object of the Integer wrapper class.
- When a is assigned to obj, Java automatically converts the primitive int into an Integer object using:
Integer obj = Integer.valueOf(a);
This is done implicitly by the compiler. You don’t have to write the conversion manually.
When Autoboxing Happens
- Assigning a primitive to a wrapper class variable:
double d = 10.5;
Double obj = d; // Autoboxing to Double
- Passing a primitive to a method expecting a wrapper object:
public void display(Integer x) {
System.out.println(x);
}
display(100); // Autoboxing from int to Integer
- Adding primitive values to Collections (like ArrayList):
ArrayList list = new ArrayList<>();
list.add(50); // Autoboxing from int to Integer
Why Autoboxing Is Useful
- Saves code: You don’t need to explicitly use valueOf().
- Works with Collections and Generics: Collections can only store objects, not primitives.
- Improves readability: Cleaner and more concise code.
Behind the Scenes
The compiler automatically rewrites:
Integer obj = 5;
as:
Integer obj = Integer.valueOf(5);
Important Note
Autoboxing creates objects, so:
- It adds memory overhead compared to primitives.
- It can be slower in performance-critical applications (e.g., inside large loops).
7. Unboxing in Java
Definition:
Unboxing is the automatic conversion performed by the Java compiler when a wrapper object is converted back to its corresponding primitive type.
In simple terms, Java extracts the primitive value from its wrapper class object without requiring explicit code from the developer.
Example:
Integer obj = 10;
int a = obj; // Unboxing
Explanation:
- obj is an object of type Integer (wrapper class).
- a is a primitive type (int).
- When the object obj is assigned to a, Java automatically performs:
int a = obj.intValue(); // Internally called during unboxing
When Unboxing Happens
- Assigning a wrapper object to a primitive variable:
Double d = 10.5;
double x = d; // Unboxing from Double to double
- Using wrapper objects in expressions:
Integer x = 5;
Integer y = 10;
int sum = x + y; // Both x and y are unboxed to perform addition
- Passing wrapper objects to methods expecting primitives:
public void printSquare(int n) {
System.out.println(n * n);
}
Integer value = 6;
printSquare(value); // Unboxing from Integer to int
Why Unboxing Is Useful
- Eliminates the need to manually call methods like .intValue(), .doubleValue(), etc.
- Allows wrapper objects to be used in mathematical operations, conditional checks, and primitive-based method calls.
- Makes code cleaner and easier to read.
Behind the Scenes
The compiler automatically rewrites:
int a = obj;
as:
int a = obj.intValue();
Similarly, for Double, it would use .doubleValue() and so on.
Important Consideration
If a wrapper object is null, unboxing will throw a NullPointerException:
Integer obj = null;
int a = obj; // Throws NullPointerException
So it's important to ensure that wrapper objects are not null before unboxing.
8. Commonly Used Methods of Wrapper Classes
Java’s wrapper classes (Integer, Double, Boolean, etc.) are not just simple containers for primitive types — they also provide a set of useful static and instance methods for converting and manipulating values.
Here are some of the most commonly used methods, especially from the Integer and Boolean classes:
1. Integer.parseInt(String s)
int num = Integer.parseInt("123");
Explanation:
- Converts a string (that represents a number) into a primitive int.
- Returns the int value 123 from the string "123".
Use Case:
Reading user input or configuration from text and converting it to a number.
Important Note:
If the string does not contain a valid number, it throws a NumberFormatException.
int n = Integer.parseInt("abc"); // Throws NumberFormatException
2. Integer.toString(int value)
String s = Integer.toString(123);
Explanation:
- Converts a primitive int to a string.
- Result: "123"
Use Case:
Useful when preparing data for display, logging, or UI output.
3. Integer.max(int a, int b)
int max = Integer.max(10, 20); // Output: 20
Explanation:
- Compares two integer values and returns the maximum of the two.
- Static method available in Integer, Double, Float, etc.
Similar Methods:
- Integer.min(a, b) – returns the minimum.
- Integer.sum(a, b) – returns the sum.
4. Boolean.parseBoolean(String s)
boolean result = Boolean.parseBoolean("true");
Explanation:
- Converts a string to a primitive boolean.
- Returns true if the string is "true" (case-insensitive); otherwise returns false.
Boolean.parseBoolean("TRUE"); // true
Boolean.parseBoolean("false"); // false
Boolean.parseBoolean("hello"); // false
Additional Useful Methods in Wrapper Classes
Method | Description |
---|---|
Double.parseDouble("3.14") | Converts string to double |
Long.parseLong("1234567") | Converts string to long |
Character.isDigit('5') | Checks if the character is a digit |
Character.toUpperCase('a') | Converts character to uppercase |
Integer.valueOf("123") | Returns an Integer object (not primitive) |
Integer.compare(10, 20) | Returns -1, 0, or 1 depending on comparison result |
9. Null Safety with Wrapper Classes
Definition:
In Java, wrapper classes (like Integer, Boolean, Double, etc.) are objects, while primitive types (like int, boolean, double, etc.) are not objects.
As objects, wrapper classes can hold a null value, but primitive types cannot. This feature provides null safety when working with scenarios where a value might be unknown, undefined, or missing — such as in database operations or API responses.
Example:
Integer x = null; // Valid
int y = null; // Compile-time error
Explanation:
- x is of type Integer (a wrapper class), so assigning null is allowed.
- y is of type int (a primitive), and primitives cannot be null — this results in a compile-time error.
Why This Is Useful
A. Working with Databases:
In a database, a numeric field (like age, salary) might have a null value if it's not set.
Integer age = resultSet.getObject("age", Integer.class); // Can be null
If age were declared as int, it wouldn't be able to hold that null — which could cause logic errors or crashes.
B. Working with APIs:
APIs might return a missing or optional value as null.
public Integer getScore() {
return null; // e.g., no score available
}
You can check:
Integer score = getScore();
if (score != null) {
System.out.println("Score is: " + score);
} else {
System.out.println("Score not available");
}
Caution: Unboxing Null Values
If you try to unbox a null wrapper object, Java will throw a NullPointerException:
Integer obj = null;
int val = obj; // Throws NullPointerException
To avoid this, always check for null before unboxing:
if (obj != null) {
int val = obj;
}
Summary:
Feature | Wrapper Class (Integer) | Primitive (int) |
---|---|---|
Can be null | Yes | No |
Used in collections | Yes | No |
Nullable from DB/API | Yes | No |
Unboxing null | Causes exception | Not applicable |
10. Performance Considerations
- Primitive types are faster and consume less memory.
- Wrapper classes are slower and can create more overhead, especially in loops.
- Use primitives when performance is critical.
11. Wrapper Classes in Collections
Java Collections Framework (like ArrayList, HashMap, etc.) is designed to work only with objects, not primitive types. Since primitive types (int, char, double, etc.) are not objects, they cannot be directly stored in collections.
To overcome this, Java uses wrapper classes (Integer, Double, Character, etc.) which act as object equivalents of primitive types.
Why Primitives Can’t Be Used in Collections
You cannot do this:
ArrayList list = new ArrayList<>(); // Compilation error
Because Java generics and collections are type-parameterized classes that require reference types (objects), not primitive data types.
How Wrapper Classes Help
Using wrapper classes, you can do this:
ArrayList list = new ArrayList<>();
list.add(10); // Autoboxing: int → Integer
list.add(20);
System.out.println(list); // Output: [10, 20]
Explanation:
- 10 is a primitive int
- Java automatically autoboxes it into an Integer object before storing it in the list
- Internally: list.add(Integer.valueOf(10));
Other Examples:
Storing characters:
ArrayList letters = new ArrayList<>();
letters.add('A'); // Autoboxed to Character
Storing boolean values:
ArrayList flags = new ArrayList<>();
flags.add(true); // Autoboxed to Boolean
Unboxing When Retrieving
When you retrieve values from collections, unboxing happens:
int val = list.get(0); // Unboxed from Integer to int
Summary Table:
Operation | With Primitive | With Wrapper |
---|---|---|
Can store in ArrayList | ❌ No | ✅ Yes |
Autoboxing supported | ❌ Not needed | ✅ Happens automatically |
Required for generics | ❌ Invalid | ✅ Required |
12. Wrapper Classes vs Parsing in Java
Java provides two key methods for converting a String containing a numeric value into a usable number:
- valueOf(String) – returns a wrapper class object
- parseInt(String) – returns a primitive type
Both are used frequently when converting user input, reading values from files, or processing strings from APIs.
A. valueOf(String)
Integer a = Integer.valueOf("123");
Explanation:
- Converts the string "123" into an Integer object (wrapper class).
- Useful when you need to store the number as an object (e.g., in collections or when null values are expected).
- Behind the scenes, it may use cached values for efficiency (for Integer, values between -128 and 127).
B. parseInt(String)
int b = Integer.parseInt("123");
Explanation:
- Converts the string "123" into a primitive int.
- Cannot be used in contexts that require an object (e.g., ArrayList is invalid).
- No object is created; more efficient in terms of memory and performance.
Key Differences:
Feature | valueOf(String) | parseInt(String) |
---|---|---|
Return type | Wrapper object (Integer) | Primitive type (int) |
Used in collections | ✅ Yes | ❌ No (must be wrapped manually) |
Memory efficient | Slightly heavier (object) | More efficient (primitive) |
Supports caching | Yes (Integer.valueOf caches -128 to 127) | No |
Autoboxing needed | No (already an object) | ✅ If assigned to object |
Autoboxing Connection:
Integer obj = Integer.parseInt("123"); // parseInt returns int → autoboxed to Integer
Java will automatically box the primitive int into an Integer object because obj is declared as Integer.
When to Use What:
Use Case | Recommended Method |
---|---|
Need a primitive for calculation | parseInt() |
Need an object for collection or null | valueOf() |
Minimizing memory in tight loops | parseInt() |
Use with generics or collections | valueOf() |
13. Wrapper Class Conversion Methods
Definition:
Each wrapper class in Java (like Integer, Double, Float, etc.) provides instance methods that allow you to convert its value to other primitive types.
These methods are especially useful when:
- You want to change the data type of a value (e.g., Integer to double)
- You’re working with mixed numeric operations
- You need manual control over type conversion (instead of relying on automatic casting)
Example:
Integer i = 100;
double d = i.doubleValue(); // Convert Integer to double
byte b = i.byteValue(); // Convert Integer to byte
Explanation:
- i is an Integer object holding the value 100.
- i.doubleValue() converts the Integer object’s value into a primitive double.
- i.byteValue() converts the same value into a primitive byte.
These methods do not change the original object; they return a new primitive value in the specified type.
Available Conversion Methods in Wrapper Classes
Each numeric wrapper class (Byte, Short, Integer, Long, Float, Double) provides the following instance methods:
Method | Description |
---|---|
byteValue() | Returns the value as a byte |
shortValue() | Returns the value as a short |
intValue() | Returns the value as an int |
longValue() | Returns the value as a long |
floatValue() | Returns the value as a float |
doubleValue() | Returns the value as a double |
Example with Multiple Conversions:
Double d = 45.67;
int i = d.intValue(); // 45
long l = d.longValue(); // 45
float f = d.floatValue(); // 45.67f
Use Case:
Scenario: Reading a numeric value as a string from input and converting it:
String priceStr = "199";
Integer price = Integer.valueOf(priceStr);
double tax = price.doubleValue() * 0.18;
System.out.println("Price with Tax: " + (price + tax));
Important Notes:
- If the original value is too large or too small, conversions to smaller types like byte or short may result in data loss (overflow or truncation).
- These methods do explicit conversions, but Java also performs implicit casting in many numeric operations.
14. Wrapper Classes and Default Values
Type | Default Value |
---|---|
int | 0 |
Integer | null |
boolean | false |
Boolean | null |
This matters when using objects as class members or in collections.
15. Best Practices
- Prefer primitive types when possible (especially in performance-critical code).
- Use wrapper classes when working with:
- Collections
- Generics
- Need for nullability
- Avoid unnecessary boxing/unboxing in loops.
Conclusion
Wrapper classes in Java bridge the gap between primitive data types and object-oriented features of the language. They enable primitives to be used in APIs that require objects, such as collections and generics. With features like autoboxing and unboxing, Java makes it easy to switch between primitives and wrappers seamlessly.
However, it's important to use wrapper classes judiciously. While they offer flexibility and functionality, they also introduce performance and memory overhead. Understanding when and why to use them is key to writing clean, efficient, and robust Java applications.