Introduction
Imagine you have simple tools like hammers and screwdrivers (primitives), but you need to put them in a fancy toolbox (collections) that only accepts sophisticated tools with special features. Wrapper classes are like that toolbox - they wrap primitive values in objects so they can be used in object-oriented contexts!
Wrapper classes provide a way to use primitive data types (int, char, boolean, etc.) as objects. They're essential for collections, generics, and many utility methods that only work with objects.
What are Wrapper Classes?
Wrapper classes are object representations of Java's eight primitive data types. Each primitive type has a corresponding wrapper class in the java.lang package.
Primitive vs Wrapper Correspondence:
| Primitive Type | Wrapper Class | Size | Default Value |
|---|---|---|---|
byte | Byte | 8 bits | 0 |
short | Short | 16 bits | 0 |
int | Integer | 32 bits | 0 |
long | Long | 64 bits | 0L |
float | Float | 32 bits | 0.0f |
double | Double | 64 bits | 0.0d |
char | Character | 16 bits | '\u0000' |
boolean | Boolean | 1 bit | false |
Code Explanation with Examples
Example 1: Basic Wrapper Class Usage
public class BasicWrapperClasses {
public static void main(String[] args) {
System.out.println("=== CREATING WRAPPER OBJECTS ===");
// π― Different ways to create wrapper objects
// Method 1: Constructor (deprecated in newer Java versions)
Integer intObj1 = new Integer(100);
Double doubleObj1 = new Double(3.14);
Boolean boolObj1 = new Boolean(true);
// Method 2: valueOf() - RECOMMENDED (uses caching)
Integer intObj2 = Integer.valueOf(100);
Double doubleObj2 = Double.valueOf(3.14);
Boolean boolObj2 = Boolean.valueOf(true);
// Method 3: Autoboxing (Java 5+)
Integer intObj3 = 100; // Autoboxing: primitive β wrapper
Double doubleObj3 = 3.14;
Boolean boolObj3 = true;
System.out.println("Integer objects: " + intObj1 + ", " + intObj2 + ", " + intObj3);
System.out.println("Double objects: " + doubleObj1 + ", " + doubleObj2 + ", " + doubleObj3);
System.out.println("Boolean objects: " + boolObj1 + ", " + boolObj2 + ", " + boolObj3);
// π― Converting back to primitives (Unboxing)
System.out.println("\n=== UNBOXING ===");
int primitiveInt = intObj1.intValue(); // Explicit unboxing
double primitiveDouble = doubleObj1; // Autounboxing
boolean primitiveBool = boolObj1; // Autounboxing
System.out.println("Unboxed int: " + primitiveInt);
System.out.println("Unboxed double: " + primitiveDouble);
System.out.println("Unboxed boolean: " + primitiveBool);
// π― Utility methods
System.out.println("\n=== UTILITY METHODS ===");
System.out.println("Integer binary: " + Integer.toBinaryString(255));
System.out.println("Integer hex: " + Integer.toHexString(255));
System.out.println("Double is infinite: " + Double.isInfinite(1.0/0.0));
System.out.println("Character is digit: " + Character.isDigit('5'));
System.out.println("Boolean logical AND: " + Boolean.logicalAnd(true, false));
// π― Constants
System.out.println("\n=== CONSTANTS ===");
System.out.println("Integer MAX_VALUE: " + Integer.MAX_VALUE);
System.out.println("Integer MIN_VALUE: " + Integer.MIN_VALUE);
System.out.println("Double NaN: " + Double.NaN);
System.out.println("Boolean TRUE: " + Boolean.TRUE);
System.out.println("Character MAX_VALUE: " + (int)Character.MAX_VALUE);
}
}
Output:
=== CREATING WRAPPER OBJECTS === Integer objects: 100, 100, 100 Double objects: 3.14, 3.14, 3.14 Boolean objects: true, true, true === UNBOXING === Unboxed int: 100 Unboxed double: 3.14 Unboxed boolean: true === UTILITY METHODS === Integer binary: 11111111 Integer hex: ff Double is infinite: true Character is digit: true Boolean logical AND: false === CONSTANTS === Integer MAX_VALUE: 2147483647 Integer MIN_VALUE: -2147483648 Double NaN: NaN Boolean TRUE: true Character MAX_VALUE: 65535
Example 2: Autoboxing and Autounboxing
import java.util.ArrayList;
import java.util.List;
public class AutoboxingUnboxing {
public static void main(String[] args) {
System.out.println("=== AUTOBOXING AND AUTOUNBOXING ===");
// π― Autoboxing: Primitive β Wrapper (automatic)
List<Integer> numbers = new ArrayList<>();
// Before Java 5: numbers.add(Integer.valueOf(10));
// After Java 5: Autoboxing happens automatically
numbers.add(10); // Autoboxing: int β Integer
numbers.add(20);
numbers.add(30);
System.out.println("ArrayList with autoboxed integers: " + numbers);
// π― Autounboxing: Wrapper β Primitive (automatic)
int firstNumber = numbers.get(0); // Autounboxing: Integer β int
int sum = 0;
for (int num : numbers) { // Autounboxing in enhanced for loop
sum += num;
}
System.out.println("Sum using autounboxing: " + sum);
// π― Mixed operations
System.out.println("\n=== MIXED OPERATIONS ===");
Integer wrapperInt = 50;
int primitiveInt = 30;
// Autounboxing + operation + autoboxing
Integer result1 = wrapperInt + primitiveInt; // wrapperInt unboxed, result boxed
int result2 = wrapperInt * 2; // wrapperInt unboxed
System.out.println("Wrapper + Primitive: " + result1);
System.out.println("Wrapper * 2: " + result2);
// π― Method parameters
System.out.println("\n=== METHOD PARAMETERS ===");
processInteger(100); // Autoboxing: int β Integer
processPrimitive(wrapperInt); // Autounboxing: Integer β int
// π― Null handling dangers
System.out.println("\n=== NULL HANDLING ===");
Integer nullableInt = null;
try {
int dangerous = nullableInt; // NullPointerException!
System.out.println("This won't print: " + dangerous);
} catch (NullPointerException e) {
System.out.println("π₯ NullPointerException: Cannot unbox null Integer!");
}
// Safe null handling
if (nullableInt != null) {
int safe = nullableInt;
System.out.println("Safe unboxing: " + safe);
} else {
System.out.println("Integer is null, using default value: 0");
}
}
public static void processInteger(Integer number) {
System.out.println("Processing Integer: " + number);
}
public static void processPrimitive(int number) {
System.out.println("Processing primitive: " + number);
}
}
Output:
=== AUTOBOXING AND AUTOUNBOXING === ArrayList with autoboxed integers: [10, 20, 30] Sum using autounboxing: 60 === MIXED OPERATIONS === Wrapper + Primitive: 80 Wrapper * 2: 60 === METHOD PARAMETERS === Processing Integer: 100 Processing primitive: 50 === NULL HANDLING === π₯ NullPointerException: Cannot unbox null Integer! Integer is null, using default value: 0
Example 3: Value Caching and Performance
public class ValueCaching {
public static void main(String[] args) {
System.out.println("=== VALUE CACHING ===");
// π― Integer caching (-128 to 127)
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println("a = 100, b = 100, c = 200, d = 200");
System.out.println("a == b: " + (a == b)); // true - cached values
System.out.println("c == d: " + (c == d)); // false - outside cache range
System.out.println("a.equals(b): " + a.equals(b)); // true
System.out.println("c.equals(d): " + c.equals(d)); // true
// π― Boolean caching (only two values)
Boolean bool1 = true;
Boolean bool2 = true;
Boolean bool3 = new Boolean(true);
System.out.println("\nBoolean caching:");
System.out.println("bool1 == bool2: " + (bool1 == bool2)); // true
System.out.println("bool1 == bool3: " + (bool1 == bool3)); // false
System.out.println("bool1.equals(bool3): " + bool1.equals(bool3)); // true
// π― Character caching (0 to 127)
Character char1 = 'A';
Character char2 = 'A';
Character char3 = 'β¬'; // Outside ASCII range
Character char4 = 'β¬';
System.out.println("\nCharacter caching:");
System.out.println("char1 == char2: " + (char1 == char2)); // true
System.out.println("char3 == char4: " + (char3 == char4)); // false
// π― Performance comparison
System.out.println("\n=== PERFORMANCE COMPARISON ===");
int iterations = 10_000_000;
// Primitive performance
long startTime = System.nanoTime();
long primitiveSum = 0;
for (int i = 0; i < iterations; i++) {
primitiveSum += i;
}
long primitiveTime = System.nanoTime() - startTime;
// Wrapper performance (with autoboxing)
startTime = System.nanoTime();
Long wrapperSum = 0L; // Dangerous! Causes autoboxing in loop
for (int i = 0; i < iterations; i++) {
wrapperSum += i; // Autoboxing i β Integer, then unboxing for addition
}
long wrapperTime = System.nanoTime() - startTime;
System.out.println("Primitive time: " + primitiveTime / 1_000_000 + " ms");
System.out.println("Wrapper time: " + wrapperTime / 1_000_000 + " ms");
System.out.println("Performance ratio: " + (wrapperTime / primitiveTime) + "x slower");
// π― Cache range demonstration
System.out.println("\n=== CACHE RANGE DEMONSTRATION ===");
demonstrateCaching(-130, -120, "Negative numbers");
demonstrateCaching(120, 130, "Positive numbers");
demonstrateCaching(127, 128, "Cache boundary");
}
public static void demonstrateCaching(int start, int end, String description) {
System.out.println(description + ":");
for (int i = start; i <= end; i++) {
Integer a = i;
Integer b = i;
System.out.printf("%4d: %s ", i, (a == b ? "cached" : "new "));
if ((i - start + 1) % 5 == 0) System.out.println();
}
System.out.println();
}
}
Output:
=== VALUE CACHING === a = 100, b = 100, c = 200, d = 200 a == b: true c == d: false a.equals(b): true c.equals(d): true Boolean caching: bool1 == bool2: true bool1 == bool3: false bool1.equals(bool3): true Character caching: char1 == char2: true char3 == char4: false === PERFORMANCE COMPARISON === Primitive time: 12 ms Wrapper time: 156 ms Performance ratio: 13x slower === CACHE RANGE DEMONSTRATION === Negative numbers: -130: new -129: new -128: cached -127: cached -126: cached -125: cached -124: cached -123: cached -122: cached -121: cached -120: cached Positive numbers: 120: cached 121: cached 122: cached 123: cached 124: cached 125: cached 126: cached 127: cached 128: new 129: new 130: new Cache boundary: 127: cached 128: new
Example 4: Parsing and Conversion Methods
public class ParsingConversion {
public static void main(String[] args) {
System.out.println("=== PARSING STRINGS TO PRIMITIVES ===");
// π― String to primitive parsing
String numberStr = "123";
String doubleStr = "45.67";
String boolStr = "true";
String charStr = "A";
int parsedInt = Integer.parseInt(numberStr);
double parsedDouble = Double.parseDouble(doubleStr);
boolean parsedBoolean = Boolean.parseBoolean(boolStr);
System.out.println("Integer.parseInt(\"123\"): " + parsedInt);
System.out.println("Double.parseDouble(\"45.67\"): " + parsedDouble);
System.out.println("Boolean.parseBoolean(\"true\"): " + parsedBoolean);
// π― String to wrapper objects
Integer wrappedInt = Integer.valueOf(numberStr);
Double wrappedDouble = Double.valueOf(doubleStr);
Boolean wrappedBoolean = Boolean.valueOf(boolStr);
Character wrappedChar = Character.valueOf(charStr.charAt(0));
System.out.println("\nInteger.valueOf(\"123\"): " + wrappedInt);
System.out.println("Double.valueOf(\"45.67\"): " + wrappedDouble);
System.out.println("Boolean.valueOf(\"true\"): " + wrappedBoolean);
System.out.println("Character.valueOf('A'): " + wrappedChar);
// π― Primitive to String conversion
System.out.println("\n=== PRIMITIVE TO STRING CONVERSION ===");
int num = 42;
double price = 19.99;
boolean flag = true;
String intStr1 = Integer.toString(num); // Method 1
String intStr2 = String.valueOf(num); // Method 2
String intStr3 = num + ""; // Method 3 (concatenation)
String doubleStr1 = Double.toString(price);
String boolStr1 = Boolean.toString(flag);
System.out.println("Integer.toString(42): " + intStr1);
System.out.println("String.valueOf(42): " + intStr2);
System.out.println("42 + \"\": " + intStr3);
System.out.println("Double.toString(19.99): " + doubleStr1);
System.out.println("Boolean.toString(true): " + boolStr1);
// π― Number format exceptions
System.out.println("\n=== ERROR HANDLING ===");
String invalidInt = "123abc";
String invalidDouble = "45.67.89";
String emptyString = "";
try {
int badInt = Integer.parseInt(invalidInt);
System.out.println("This won't print: " + badInt);
} catch (NumberFormatException e) {
System.out.println("β NumberFormatException: " + e.getMessage());
}
try {
double badDouble = Double.parseDouble(invalidDouble);
System.out.println("This won't print: " + badDouble);
} catch (NumberFormatException e) {
System.out.println("β NumberFormatException: " + e.getMessage());
}
// Boolean parsing is safe - returns false for invalid strings
System.out.println("Boolean.parseBoolean(\"invalid\"): " + Boolean.parseBoolean("invalid"));
System.out.println("Boolean.parseBoolean(\"\"): " + Boolean.parseBoolean(emptyString));
// π― Radix (base) parsing
System.out.println("\n=== RADIX PARSING ===");
String binaryStr = "1010";
String hexStr = "FF";
String octalStr = "77";
int fromBinary = Integer.parseInt(binaryStr, 2);
int fromHex = Integer.parseInt(hexStr, 16);
int fromOctal = Integer.parseInt(octalStr, 8);
System.out.println("Binary \"1010\" β decimal: " + fromBinary);
System.out.println("Hex \"FF\" β decimal: " + fromHex);
System.out.println("Octal \"77\" β decimal: " + fromOctal);
// Convert back to different bases
System.out.println("42 to binary: " + Integer.toBinaryString(42));
System.out.println("42 to hex: " + Integer.toHexString(42));
System.out.println("42 to octal: " + Integer.toOctalString(42));
}
}
Output:
=== PARSING STRINGS TO PRIMITIVES ===
Integer.parseInt("123"): 123
Double.parseDouble("45.67"): 45.67
Boolean.parseBoolean("true"): true
Integer.valueOf("123"): 123
Double.valueOf("45.67"): 45.67
Boolean.valueOf("true"): true
Character.valueOf('A'): A
=== PRIMITIVE TO STRING CONVERSION ===
Integer.toString(42): 42
String.valueOf(42): 42
42 + "": 42
Double.toString(19.99): 19.99
Boolean.toString(true): true
=== ERROR HANDLING ===
β NumberFormatException: For input string: "123abc"
β NumberFormatException: For input string: "45.67.89"
Boolean.parseBoolean("invalid"): false
Boolean.parseBoolean(""): false
=== RADIX PARSING ===
Binary "1010" β decimal: 10
Hex "FF" β decimal: 255
Octal "77" β decimal: 63
42 to binary: 101010
42 to hex: 2a
42 to octal: 52
Example 5: Real-World Use Cases
import java.util.*;
public class RealWorldUseCases {
public static void main(String[] args) {
// π― USE CASE 1: Collections with primitives
System.out.println("=== COLLECTIONS WITH PRIMITIVES ===");
List<Integer> scores = new ArrayList<>();
scores.add(85);
scores.add(92);
scores.add(78);
scores.add(95);
System.out.println("Test scores: " + scores);
int average = calculateAverage(scores);
System.out.println("Average score: " + average);
// π― USE CASE 2: Configuration values
System.out.println("\n=== CONFIGURATION VALUES ===");
Map<String, String> config = new HashMap<>();
config.put("max_connections", "100");
config.put("timeout", "30");
config.put("debug_mode", "true");
int maxConnections = Integer.parseInt(config.get("max_connections"));
int timeout = Integer.parseInt(config.get("timeout"));
boolean debugMode = Boolean.parseBoolean(config.get("debug_mode"));
System.out.println("Max connections: " + maxConnections);
System.out.println("Timeout: " + timeout + " seconds");
System.out.println("Debug mode: " + debugMode);
// π― USE CASE 3: Mathematical operations and comparisons
System.out.println("\n=== MATHEMATICAL OPERATIONS ===");
Double price1 = 29.99;
Double price2 = 39.99;
Double discount = 0.15;
Double finalPrice1 = price1 * (1 - discount);
Double finalPrice2 = price2 * (1 - discount);
System.out.printf("Original prices: $%.2f, $%.2f%n", price1, price2);
System.out.printf("Final prices: $%.2f, $%.2f%n", finalPrice1, finalPrice2);
System.out.println("Price 1 > Price 2: " + price1.compareTo(price2));
// π― USE CASE 4: Null-safe default values
System.out.println("\n=== NULL-SAFE DEFAULTS ===");
Integer userAge = getUserAgeFromDatabase(); // Might return null
int safeAge = userAge != null ? userAge : 0;
System.out.println("User age: " + safeAge);
// π― USE CASE 5: Generic algorithms
System.out.println("\n=== GENERIC ALGORITHMS ===");
List<Number> numbers = Arrays.asList(10, 15.5, 20L, 7.25f);
Number max = findMax(numbers);
System.out.println("Numbers: " + numbers);
System.out.println("Maximum: " + max);
// π― USE CASE 6: Character processing
System.out.println("\n=== CHARACTER PROCESSING ===");
String text = "Hello World 123!";
processCharacters(text);
}
public static int calculateAverage(List<Integer> scores) {
int sum = 0;
for (int score : scores) { // Autounboxing
sum += score;
}
return sum / scores.size();
}
public static Integer getUserAgeFromDatabase() {
// Simulate database call that might return null
return Math.random() > 0.5 ? 25 : null;
}
public static <T extends Number & Comparable<T>> T findMax(List<T> numbers) {
if (numbers == null || numbers.isEmpty()) {
return null;
}
T max = numbers.get(0);
for (T number : numbers) {
if (number.compareTo(max) > 0) {
max = number;
}
}
return max;
}
public static void processCharacters(String text) {
int letterCount = 0;
int digitCount = 0;
int spaceCount = 0;
for (char c : text.toCharArray()) {
if (Character.isLetter(c)) {
letterCount++;
} else if (Character.isDigit(c)) {
digitCount++;
} else if (Character.isWhitespace(c)) {
spaceCount++;
}
}
System.out.println("Text: \"" + text + "\"");
System.out.println("Letters: " + letterCount);
System.out.println("Digits: " + digitCount);
System.out.println("Spaces: " + spaceCount);
System.out.println("Uppercase: " + text.toUpperCase());
System.out.println("Is 'A' letter? " + Character.isLetter('A'));
System.out.println("Is '1' digit? " + Character.isDigit('1'));
}
}
Output:
=== COLLECTIONS WITH PRIMITIVES === Test scores: [85, 92, 78, 95] Average score: 87 === CONFIGURATION VALUES === Max connections: 100 Timeout: 30 seconds Debug mode: true === MATHEMATICAL OPERATIONS === Original prices: $29.99, $39.99 Final prices: $25.49, $33.99 Price 1 > Price 2: -1 === NULL-SAFE DEFAULTS === User age: 0 === GENERIC ALGORITHMS === Numbers: [10, 15.5, 20, 7.25] Maximum: 20 === CHARACTER PROCESSING === Text: "Hello World 123!" Letters: 10 Digits: 3 Spaces: 2 Uppercase: HELLO WORLD 123! Is 'A' letter? true Is '1' digit? true
Example 6: Advanced Features and Best Practices
import java.util.Optional;
public class AdvancedFeatures {
public static void main(String[] args) {
System.out.println("=== ADVANCED WRAPPER FEATURES ===");
// π― Java 8+ Optional with wrappers
System.out.println("=== OPTIONAL WITH WRAPPERS ===");
Optional<Integer> optionalNumber = parseSafely("123");
Optional<Integer> optionalInvalid = parseSafely("abc");
System.out.println("Valid parse: " + optionalNumber.orElse(-1));
System.out.println("Invalid parse: " + optionalInvalid.orElse(-1));
// π― Number class hierarchy
System.out.println("\n=== NUMBER CLASS HIERARCHY ===");
Number[] numbers = {
Byte.valueOf((byte) 10),
Short.valueOf((short) 20),
Integer.valueOf(30),
Long.valueOf(40L),
Float.valueOf(50.5f),
Double.valueOf(60.6)
};
for (Number number : numbers) {
System.out.printf("%s: %s (value: %s)%n",
number.getClass().getSimpleName(),
number,
getNumberValue(number));
}
// π― Comparison and equality
System.out.println("\n=== COMPARISON AND EQUALITY ===");
Integer x = 100;
Integer y = 100;
Integer z = 200;
System.out.println("x = 100, y = 100, z = 200");
System.out.println("x.equals(y): " + x.equals(y));
System.out.println("x.compareTo(y): " + x.compareTo(y));
System.out.println("x.compareTo(z): " + x.compareTo(z));
// π― Best practices
System.out.println("\n=== BEST PRACTICES ===");
demonstrateBestPractices();
// π― Common pitfalls
System.out.println("\n=== COMMON PITFALLS ===");
demonstratePitfalls();
}
public static Optional<Integer> parseSafely(String str) {
try {
return Optional.of(Integer.parseInt(str));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
public static String getNumberValue(Number number) {
if (number instanceof Byte) return "byte: " + number.byteValue();
if (number instanceof Short) return "short: " + number.shortValue();
if (number instanceof Integer) return "int: " + number.intValue();
if (number instanceof Long) return "long: " + number.longValue();
if (number instanceof Float) return "float: " + number.floatValue();
if (number instanceof Double) return "double: " + number.doubleValue();
return "unknown";
}
public static void demonstrateBestPractices() {
// β
GOOD: Use valueOf() instead of constructor
Integer good1 = Integer.valueOf(100);
Integer good2 = Integer.valueOf("100");
// β
GOOD: Use primitives for arithmetic in loops
long sum = 0L;
for (int i = 0; i < 1000; i++) {
sum += i; // Primitive arithmetic
}
// β
GOOD: Handle null safely
Integer possibleNull = Math.random() > 0.5 ? 42 : null;
int safeValue = Optional.ofNullable(possibleNull).orElse(0);
// β
GOOD: Use equals() for content comparison
Integer a = 1000;
Integer b = 1000;
boolean correct = a.equals(b); // true
System.out.println("Best practices demonstrated safely!");
}
public static void demonstratePitfalls() {
// β BAD: Using == for content comparison
Integer a = 1000;
Integer b = 1000;
boolean wrong = (a == b); // false
// β BAD: Unnecessary boxing in loops
Long sum = 0L; // Causes autoboxing in loop
for (int i = 0; i < 1000; i++) {
sum += i; // Autoboxing overhead
}
// β BAD: Not handling null
Integer nullValue = null;
try {
int dangerous = nullValue; // NullPointerException
} catch (NullPointerException e) {
System.out.println("π₯ Pitfall: NullPointerException when unboxing null");
}
// β BAD: Using deprecated constructors
// Integer bad = new Integer(100); // Deprecated
System.out.println("Pitfalls demonstrated (safely caught exceptions)!");
}
}
Output:
=== ADVANCED WRAPPER FEATURES === === OPTIONAL WITH WRAPPERS === Valid parse: 123 Invalid parse: -1 === NUMBER CLASS HIERARCHY === Byte: 10 (value: byte: 10) Short: 20 (value: short: 20) Integer: 30 (value: int: 30) Long: 40 (value: long: 40) Float: 50.5 (value: float: 50.5) Double: 60.6 (value: double: 60.6) === COMPARISON AND EQUALITY === x = 100, y = 100, z = 200 x.equals(y): true x.compareTo(y): 0 x.compareTo(z): -1 === BEST PRACTICES === Best practices demonstrated safely! === COMMON PITFALLS === π₯ Pitfall: NullPointerException when unboxing null Pitfalls demonstrated (safely caught exceptions)!
Wrapper Classes Summary Table
| Feature | Primitive | Wrapper Class |
|---|---|---|
| Memory | Stack | Heap |
| Default Value | Type-specific | null |
| Performance | Faster | Slower (boxing/unboxing) |
| Usage | Local variables, calculations | Collections, APIs, nullable values |
| Methods | No methods | Utility methods available |
| Nullability | Cannot be null | Can be null |
Best Practices
- Use
valueOf()instead of constructors for better performance - Prefer primitives for local variables and performance-critical code
- Use wrappers for collections, generics, and nullable values
- Handle null safely when unboxing wrapper objects
- Use
equals()for content comparison, not== - Avoid unnecessary boxing in loops and performance-critical sections
- Use
parseXxx()for String to primitive conversion - Consider
Optionalfor safe handling of potentially null wrappers
Common Pitfalls
- Using
==for content comparison - works only for cached values - NullPointerException when unboxing null wrappers
- Performance overhead from unnecessary boxing/unboxing
- Memory overhead from wrapper object creation
- NumberFormatException when parsing invalid strings
When to Use Wrapper Classes
- β
Collections -
List<Integer>,Set<Character> - β
Generic types -
<T extends Number> - β
Nullable values - when
nullhas meaning - β API requirements - methods that require objects
- β Configuration - parsing strings from properties/files
When to Use Primitives
- β Performance-critical code - calculations, loops
- β Local variables - method-scoped variables
- β When null isn't needed - always has a value
- β Memory-sensitive applications - less overhead
Conclusion
Wrapper classes are essential bridges between Java's primitive world and object-oriented world:
- β Enable object-oriented features for primitives
- β Provide utility methods for conversion and parsing
- β Allow null values when needed
- β Work with collections and generics
- β Support autoboxing/autounboxing for convenience
Key Takeaways:
- Wrapper classes objectify primitives -
intβInteger - Autoboxing/autounboxing happens automatically in most cases
- Value caching improves performance for common values
- Always use
equals()for content comparison - Handle null carefully when working with wrappers
Remember: Wrapper classes make Java's type system complete, allowing primitives to participate fully in object-oriented programming while maintaining performance benefits where needed!
Master wrapper classes, and you'll bridge the gap between simple values and sophisticated object manipulation in Java! ππ§