Chapter 31:Wrapper Classes in Java: An In-Depth Guide for Interviews
Introduction
Wrapper classes in Java serve the critical purpose of converting primitive data types into objects. This allows developers to use object-oriented programming concepts seamlessly with primitives, while also leveraging utility methods for efficient coding.
Why Do We Need Wrapper Classes?
The primary reasons for the existence of wrapper classes are:
Storing Primitive Data as Objects: Some data structures, like collections, work only with objects.
Utility Methods: Wrapper classes come with built-in methods that simplify operations on primitive data types.
Object-Oriented Flexibility: Java is an object-oriented language, and wrapper classes help incorporate primitive data types into this paradigm.
Hierarchy of Wrapper Classes
All wrapper classes are part of the java.lang
package and extend the Object
class. Below is the hierarchy structure:
Object Class Hierarchy:
Object
|
-------------------
| |
String Wrapper Classes
|
-----------------------------------------
| | |
Boolean Character Number
|
----------------------------------
| | | | |
Byte Short Integer Long Float/Double
Key Commands to Explore Wrapper Classes
You can inspect the methods and details of wrapper classes using the javap
command. For instance, examining the Integer
class:
javap java.lang.Integer
This command reveals methods like valueOf()
, parseXxx()
, and toString()
available in the Integer
wrapper class.
Important Methods in Wrapper Classes
valueOf()
Method in Java
1. What is the valueOf()
Method?
1.1. The valueOf()
method is used to:
Convert primitive type data or strings to wrapper objects.
Provide an alternative to the constructors of wrapper classes (e.g.,
Integer(int)
).
1.2. Why is it preferred?
More efficient than constructors due to caching.
Ensures type safety during conversions.
1.3. Wrapper Classes Supporting valueOf()
:
- Every wrapper class (except
Character
) has a staticvalueOf()
method.
1.4. Forms of the valueOf()
Method:
Primitive to Wrapper:
Example:Integer.valueOf(int)
String to Wrapper:
Example:Integer.valueOf(String)
String with Radix to Wrapper:
Example:Integer.valueOf(String, int radix)
2. Primitive to Wrapper Conversion
2.1. Method Signature:
public static java.lang.Integer valueOf(int);
2.2. Example of Primitive to Wrapper Conversion:
Integer i = Integer.valueOf(10);
System.out.println(i); // Output: 10
- Explanation: The primitive
int
value10
is converted to anInteger
object.
2.3. Why is this method preferred?
- Uses cached objects for common values (e.g.,
-128
to127
forInteger
).
2.4. Example Illustrating Caching:
Integer a = Integer.valueOf(100);
Integer b = Integer.valueOf(100);
System.out.println(a == b); // Output: true
Integer c = Integer.valueOf(200);
Integer d = Integer.valueOf(200);
System.out.println(c == d); // Output: false
- Reason: Values between
-128
and127
are cached, reducing memory usage.
3. String to Wrapper Conversion
3.1. Method Signature:
public static java.lang.Integer valueOf(String);
3.2. Example of String to Wrapper Conversion:
Integer i = Integer.valueOf("10");
System.out.println(i); // Output: 10
- Explanation: The string
"10"
is converted to anInteger
object.
3.3. Invalid Input Handling:
- If a non-numeric string (e.g.,
"ten"
) is passed, it throws aNumberFormatException
.
3.4. Example of Exception Handling:
try {
Integer i = Integer.valueOf("ten");
} catch (NumberFormatException e) {
System.out.println("Error: " + e.getMessage());
}
// Output: Error: For input string: "ten"
4. String with Radix Conversion
4.1. Method Signature:
public static java.lang.Integer valueOf(String, int radix);
4.2. What is Radix?
Radix represents the base of the number system.
Common Radices:
Base 2 (Binary): Digits 0-1.
Base 8 (Octal): Digits 0-7.
Base 10 (Decimal): Digits 0-9.
Base 16 (Hexadecimal): Digits 0-9, A-F.
4.3. Example with Base 2:
Integer binary = Integer.valueOf("100", 2);
System.out.println(binary); // Output: 4
- Explanation: The binary string
"100"
is interpreted as4
in decimal.
4.4. Example with Base 16:
Integer hex = Integer.valueOf("A", 16);
System.out.println(hex); // Output: 10
4.5. Invalid Radix Handling:
Radix must be between
Character.MIN_RADIX
(2) andCharacter.MAX_RADIX
(36).Example:
try {
Integer invalid = Integer.valueOf("100", 37);
} catch (NumberFormatException e) {
System.out.println("Error: " + e.getMessage());
}
// Output: Error: radix 37 greater than Character.MAX_RADIX
5. Understanding Character.MIN_RADIX and Character.MAX_RADIX
5.1. Definition:
Character.MIN_RADIX
: The smallest allowed radix (2).Character.MAX_RADIX
: The largest allowed radix (36).
5.2. How to Find Radices:
System.out.println("MIN_RADIX: " + Character.MIN_RADIX); // Output: 2
System.out.println("MAX_RADIX: " + Character.MAX_RADIX); // Output: 36
5.3. Why Radices are Configured for 2 to 36:
- Ensures compatibility with number systems commonly used in computing.
6. Advanced Use Cases
6.1. Converting Binary to Decimal:
Integer binary = Integer.valueOf("1101", 2);
System.out.println(binary); // Output: 13
6.2. Converting Hexadecimal to Decimal:
Integer hex = Integer.valueOf("1A", 16);
System.out.println(hex); // Output: 26
6.3. Unsupported Bases:
- Attempting to convert using unsupported bases throws an exception:
Integer i = Integer.valueOf("123", 40); // Invalid radix
// Throws NumberFormatException
7. Limitations of valueOf()
7.1. Performance Considerations:
- For larger ranges beyond the cache limit, objects are created every time.
7.2. Error-Prone Input:
- Passing invalid strings can lead to runtime exceptions.
8. Conclusion
The
valueOf()
method is a powerful tool for creating wrapper objects from primitives or strings.By understanding its nuances, including caching, radix handling, and input validation, developers can use it effectively in Java applications.