Java Wrapper Classes Explained
Java provides primitive data types such as int, long, double, char, and boolean for storing simple values. Wrapper classes provide object representations of these primitive types. They are especially important when working with collections, generics, APIs, and frameworks that require objects.
Primitive Types and Wrapper Classes
- byte → Byte
- short → Short
- int → Integer
- long → Long
- float → Float
- double → Double
- char → Character
- boolean → Boolean
Primitive vs Wrapper Class
The biggest difference is that a primitive stores a value directly, while a wrapper variable refers to an object. For example, int is a primitive type and Integer is its wrapper class.
int a = 100;
Integer b = 100;- int is a primitive type.
- Integer is an object type.
- int cannot contain null.
- Integer can contain null.
- Integer can be used with generics and collections.
Why Are Wrapper Classes Needed?
- Java generics work with reference types.
- Collections such as ArrayList use wrapper types instead of primitives.
- Wrapper classes provide useful conversion and utility methods.
- Some frameworks and APIs require objects.
- Wrapper objects can represent null.
Wrapper Classes with Collections
You cannot declare a generic collection such as ArrayList<int>. Java generics require reference types, so Integer is used instead.
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);When 10 and 20 are added, Java automatically converts the primitive int values into Integer objects. This automatic primitive-to-wrapper conversion is called autoboxing.
What Is Autoboxing?
Autoboxing is the automatic conversion of a primitive value into its corresponding wrapper object.
int x = 100;
Integer a = x;The programmer writes Integer a = x, but Java automatically performs the primitive-to-wrapper conversion. Conceptually, this is similar to using Integer.valueOf(x).
Important Difference: Boxing vs Autoboxing
int x = 100;
Integer a = Integer.valueOf(x); // Explicit boxing
Integer b = x; // AutoboxingBoth examples convert int to Integer, but the first explicitly calls Integer.valueOf(), while the second relies on the compiler to perform the conversion automatically. Therefore, Integer.valueOf() is an explicit boxing operation, whereas Integer b = x is autoboxing.
What Is Integer.valueOf()?
Integer.valueOf() returns an Integer object representing a given int value. It is preferred over manually creating Integer objects because it can reuse cached Integer instances.
Integer a = Integer.valueOf(100);The important point is that valueOf() does not perform unboxing. It returns an Integer object. Unboxing is performed when an Integer is converted into an int.
What Is Unboxing?
Unboxing is the conversion of a wrapper object into its corresponding primitive type.
Integer a = 100;
int b = a;Here Java automatically extracts the int value from the Integer object. Conceptually, this is similar to calling a.intValue().
Explicit Unboxing
Integer a = 100;
int b = a.intValue();intValue() explicitly converts an Integer object into a primitive int.
Autoboxing and Unboxing Together
Integer a = 10;
Integer b = 20;
Integer c = a + b;The arithmetic operation requires primitive numeric values. Java therefore unboxes a and b, performs the addition as primitive int arithmetic, and then boxes the result back into an Integer.
Integer c = Integer.valueOf(a.intValue() + b.intValue());The code above is a conceptual representation of what happens. The compiler and JVM implementation details are more involved.
What Happens When Integer Is Incremented?
Integer b = 100;
b++;The increment operation involves unboxing and boxing. Java needs the primitive value to perform the arithmetic operation, then the resulting value is represented as an Integer again.
b = Integer.valueOf(b.intValue() + 1);This is a conceptual explanation: first Integer is converted to int, one is added, and the result is converted back to Integer.
Integer Caching in Java
Integer caching is a mechanism where Java can reuse Integer objects representing commonly used integer values instead of creating a separate object every time.
What Is the Integer Cache Range?
The standard Integer.valueOf() implementation always caches Integer values from -128 through 127, inclusive. It may also cache values outside this range, so code should never depend on a particular cache range beyond the guaranteed range.
- -128 → cached
- -1 → cached
- 0 → cached
- 100 → cached
- 127 → cached
- 128 → caching is not guaranteed
- 1000 → caching is not guaranteed
The Java specification guarantees consistent identity for certain boxing conversions in the -128 to 127 integer range. The Integer API also specifies that valueOf() always caches this range and may cache other values.
Why Does Java Cache Integers?
Small integer values occur frequently in typical programs. Reusing commonly requested wrapper objects can reduce unnecessary object creation and improve memory and performance characteristics.
Integer Caching Example
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true
System.out.println(a.equals(b)); // trueBecause 100 is inside the guaranteed Integer cache range, these two boxing conversions can refer to the same cached Integer object.
Integer Values Outside the Cache
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // normally false
System.out.println(a.equals(b)); // trueFor values outside the guaranteed cache range, you must not assume that two Integer references point to the same object. equals() still compares their numeric values.
The Important a, b, and c Example
Integer a = 100;
Integer b = 100;
Integer c = 101;All three values are inside the guaranteed Integer cache range. Therefore, a and b refer to the cached representation of 100, while c refers to the cached representation of 101.
System.out.println(a == b); // true
System.out.println(a.equals(b)); // true
System.out.println(a == c); // false
System.out.println(a.equals(c)); // false
System.out.println(b == c); // false
System.out.println(b.equals(c)); // falseWhat Happens After Incrementing b?
Integer a = 100;
Integer b = 100;
Integer c = 101;
b++;After b++, the values are a = 100, b = 101, and c = 101. The increment conceptually unboxes b, adds one, and boxes 101 again. Since 101 is inside the guaranteed cache range, b can refer to the same cached Integer object as c.
System.out.println(a == b); // false
System.out.println(a.equals(b)); // false
System.out.println(a == c); // false
System.out.println(a.equals(c)); // false
System.out.println(b == c); // true
System.out.println(b.equals(c)); // trueWhy == Can Be Dangerous with Integer
When Integer objects are compared using ==, Java compares object references rather than numeric values. Integer caching can make two different Integer variables refer to the same cached object, causing == to return true.
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true because of cached identity
System.out.println(a.equals(b)); // true because values are equalFor Integer value comparison, use equals() or compare primitive values rather than depending on object identity.
Integer == vs equals()
- == compares object references when both operands are Integer objects.
- equals() compares the numeric value represented by Integer objects.
- Integer caching can make == return true for cached values.
- Use equals() when you want to compare Integer values.
What Happens When Integer Is null?
Integer value = null;
int number = value;This causes a NullPointerException because Java attempts to unbox the null Integer into an int. A primitive int cannot represent null.
String and Wrapper Classes
String is not a wrapper class. Java does not have a primitive string type, so String does not participate in primitive-to-wrapper autoboxing or wrapper-to-primitive unboxing.
String Comparison
String a = "hello";
String b = "hello";
System.out.println(a == b); // true in this example
System.out.println(a.equals(b)); // trueString literals can be stored in the String pool and identical literals can share the same object. However, == still compares references. equals() compares String contents.
String a = "hello";
String b = new String("hello");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // trueThe new String expression creates a separate String object, while equals() checks whether both strings contain the same characters.
Integer vs String: Interview Comparison
- Integer is a wrapper class for primitive int.
- String is not a wrapper class.
- int → Integer can happen through autoboxing.
- Integer → int can happen through unboxing.
- String has no primitive counterpart in Java.
- Integer has caching for a guaranteed range of -128 to 127.
- String literals can use the String pool.
- == compares object references.
- equals() compares logical values or contents.
Useful Integer Methods
- Integer.parseInt("100") → returns primitive int
- Integer.valueOf("100") → returns Integer
- Integer.valueOf(100) → returns Integer
- integer.intValue() → returns primitive int
- Integer.toString(100) → converts an int value to String
parseInt() vs valueOf()
int a = Integer.parseInt("100");
Integer b = Integer.valueOf("100");- parseInt() returns int.
- valueOf() returns Integer.
- valueOf() can reuse cached Integer objects.
Java Wrapper Classes Interview Questions and Answers
Q1. What is a wrapper class in Java?
Short Answer: A wrapper class represents a primitive value as an object.
Detailed Answer: Java provides wrapper classes such as Integer, Long, Double, Character, and Boolean to represent primitive values as objects. They are useful with collections, generics, frameworks, and APIs that require reference types.
Q2. What is autoboxing?
Short Answer: Autoboxing is the automatic conversion of a primitive value into its wrapper object.
Detailed Answer: When Java expects an object but receives a compatible primitive, the compiler automatically performs boxing. For example, Integer x = 100 automatically converts the int value into an Integer.
Q3. What is unboxing?
Short Answer: Unboxing converts a wrapper object into its corresponding primitive type.
Detailed Answer: If Java needs a primitive but receives a wrapper object, it can automatically extract the primitive value. For example, int x = integerObject automatically unboxes Integer into int.
Q4. Is Integer.valueOf() autoboxing?
Short Answer: No. Integer.valueOf() is an explicit boxing operation.
Detailed Answer: Integer.valueOf(100) explicitly calls a method that returns an Integer object. Autoboxing occurs when Java performs the primitive-to-wrapper conversion automatically, such as Integer x = 100.
Q5. What does Integer.valueOf() do?
Short Answer: It returns an Integer object representing a given int value.
Detailed Answer: Integer.valueOf() creates or reuses an Integer representation of the supplied value. It is important because it can use the Integer cache for commonly used values.
Q6. What is the Integer cache range?
Short Answer: The guaranteed Integer cache range is -128 to 127 inclusive.
Detailed Answer: Integer.valueOf() always caches values from -128 through 127. Implementations may cache additional values, so values outside this range should not be assumed to have shared object identity.
Q7. Why does Java cache Integer objects?
Short Answer: To reuse commonly used Integer objects and avoid unnecessary object creation.
Detailed Answer: Small integer values are common in Java programs. Reusing cached objects can reduce repeated object allocation. The language specification guarantees identity for certain commonly boxed values, while the Integer API guarantees caching from -128 to 127.
Q8. What is the output of Integer a = 100; Integer b = 100; a == b?
Short Answer: true.
Detailed Answer: 100 is inside the guaranteed Integer cache range. Autoboxing can therefore produce references to the same cached Integer object, making == true in this case.
Q9. What is the output of Integer a = 1000; Integer b = 1000; a == b?
Short Answer: Do not rely on it being true; it is normally false.
Detailed Answer: 1000 is outside the guaranteed cache range. The Java specification does not guarantee that separate boxing operations will produce the same object for this value. Therefore == should never be used for Integer value comparison.
Q10. What is the difference between == and equals() for Integer?
Short Answer: == compares references, while equals() compares Integer values.
Detailed Answer: Integer is an object, so == checks whether two references point to the same object. equals() checks whether the represented integer values are equal. Integer caching can make == appear to work for some values, but equals() is the correct choice for value comparison.
Q11. What happens when b++ is used on an Integer?
Short Answer: Java unboxes the Integer, performs the increment, and boxes the result.
Detailed Answer: For Integer b = 100; b++; Java conceptually obtains the primitive value, adds one, and converts the result back to Integer. Since 101 is cached, the resulting Integer can refer to the cached 101 object.
Q12. What happens when an Integer containing null is unboxed?
Short Answer: A NullPointerException occurs.
Detailed Answer: Integer is a reference type and can contain null, but int cannot. When Java tries to unbox null into int, it cannot obtain a primitive value and throws NullPointerException.
Q13. Is String a wrapper class?
Short Answer: No. String is a regular Java class, not a wrapper class.
Detailed Answer: Java has no primitive string type, so String does not wrap a primitive. It therefore does not participate in autoboxing or unboxing. String has its own behavior, including immutability and string pooling.
Q14. Why can String == return true?
Short Answer: String literals can refer to the same object from the String pool.
Detailed Answer: Java can store string literals in a shared String pool. When two identical literals refer to the same pooled object, == can return true. However, == always checks reference identity, so equals() should be used to compare String contents.
Q15. What is the difference between parseInt() and valueOf()?
Short Answer: parseInt() returns int, while valueOf() returns Integer.
Detailed Answer: Integer.parseInt("100") converts the String into a primitive int. Integer.valueOf("100") converts the String into an Integer object. valueOf() can also take advantage of Integer caching.
Quick Interview Revision Table
- int → Integer = boxing/autoboxing
- Integer → int = unboxing/auto-unboxing
- Integer.valueOf(100) = explicit boxing
- Integer.intValue() = explicit unboxing
- Integer cache guaranteed range = -128 to 127
- Integer values outside that range are not guaranteed to share identity
- == = reference comparison for Integer objects
- equals() = value comparison for Integer objects
- Integer can be null
- int cannot be null
- String is not a wrapper class
- String literals can be stored in the String pool
- String == compares references
- String.equals() compares contents
- ArrayList<int> is invalid
- ArrayList<Integer> is valid
Final Interview Takeaway
For Java interviews, remember the complete flow: primitive types can be converted to wrapper objects through boxing, Java can perform that conversion automatically through autoboxing, wrapper objects can be converted back through unboxing, and Integer.valueOf() can reuse cached objects. The guaranteed Integer cache range is -128 to 127. Because == compares object identity, Integer values should normally be compared with equals(). String is different because it is not a wrapper class and uses String pooling for literals.