Item 49 - Prefer primitive types to boxed primitives
From Effective Java 2/e by Joshua Bloch
Three differences
- Primitives have only their values, whereas boxed primitives have identities distinct from their values
- Primitive types have only fully functional values, whereas each boxed primitive type has one nonfunctional value which is null
- Primitives are generally more time- and space-efficient than boxed primitives
Example #1
// naturalOrder.compare(new Integer(42), new Integer(42)) == 1 (should be 0)
Comparator<Integer> naturalOrder = new Comparator<Integer>() {
public int compare(Integer first, Integer second) {
return first < second ? -1 : (first == second ? 0 : 1);
}
};
// naturalOrder.compare(new Integer(42), new Integer(42)) == 0
Comparator<Integer> naturalOrder = new Comparator<Integer>() {
public int compare(Integer first, Integer second) {
int f = first; // Auto-unboxing
int s = second; // Auto-unboxing
return f < s ? -1 : (f == s ? 0 : 1); // No unboxing
}
};
Example #2
// It throws a NullPointerException when evaluating the expression (i == 42)
public class Unbelievable {
static Integer i;
public static void main(String[] args) {
if (i == 42)
System.out.println("Unbelievable");
}
}
In nearly every case when you mix primitives and boxed primitives in a single operation, the boxed primitive is auto-unboxed
Example #3
// Hideously slow program! Can you spot the object creation?
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);
}
Conclusion
- Autoboxing reduces the verbosity, but not the danger, of using boxed primitives
- When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw a NullPointerException