Use boxing with care
Boxing
was introduced in JDK 1.5 to eliminate trivial conversions between primitives
(int, boolean, etc) and corresponding wrapper objects
(Integer, Boolean, etc).
Boxing allows some code to be a bit more concise and legible.
It's also useful when using collections (which only take objects, not primitives).
An example run of this class :
There are two complimentary aspects of boxing:
- auto-boxing, which refers to automatic conversion of an int to an Integer, for example
- auto-unboxing, which refers to automatic conversion of a Boolean to a boolean, for example
Boxing partially hides the distinction between primitives and corresponding wrapper objects, but it doesn't remove it. There are two distinctions which are not changed by boxing:
- objects can be null, while primitives cannot
- objects have both state and identity, while primitives have only state (the value)
Some points to remember:
- be careful with nulls. Auto-unboxing a null object will cause a NullPointerException.
- comparing items with == and equals must be done with care.
If x and y are either both primitives, or both objects, then no boxing occurs:
Operation | Two primitives | Two objects |
x == y | compare value | compare identity |
x.equals(y) | does not compile | compare value |
If one item is a primitive, and the other item is a corresponding wrapper object, then boxing can occur:
Operation | Behavior |
x == y | treat as two primitives, and compare value |
x.equals(y) | does not compile if x is a primitive; otherwise treat as two objects, and compare value |
Example
import java.util.*; public final class BoxingExamples { public static final void main(String... aArgs){ //pass Integer where int expected explode(new Integer(3)); //pass literal where Boolean expected tellTruth(true); //calculate "int-erchangably" with int and Integer Integer integerYear = new Integer(1989); Integer otherIntegerYear = integerYear + 10; int intYear = integerYear + new Integer(15); log(integerYear.toString()); log(otherIntegerYear.toString()); System.out.println(intYear); /* * Comparison of primitives and wrapper objects using == and equals. * * When both items are of the same type : * 2 primitives 2 objects * ---------------------------------------------------------- * == : value identity * equals() : not applicable value * * * When one item is a primitive, and the other is an object : * == : treat as two primitives * x.equals(y) : treat as two objects; do not compile if x is primitive */ intYear = 1880; integerYear = new Integer(1880); if (intYear == integerYear){ log("intYear == integerYear: TRUE"); // yes } else { log("intYear == integerYear : FALSE"); } if (integerYear.equals(intYear)){ log("integerYear.equals(intYear): TRUE"); //yes } else { log("integerYear.equals(intYear): FALSE"); } //does not compile "int cannot be dereferenced" : //intYear.equals(integerYear); intYear = 1881; //new value if (intYear == integerYear){ log("intYear == integerYear: TRUE"); } else { log("intYear == integerYear : FALSE"); // yes } if (integerYear.equals(intYear)){ log("integerYear.equals(intYear): TRUE"); } else { log("integerYear.equals(intYear): FALSE"); //yes } } // PRIVATE private static void explode(int aNumTimes){ log("Exploding " + aNumTimes + " times."); } private static void tellTruth(Boolean aChoice){ //instead of if ( aChoice.booleanValue() ) { if (aChoice) { log("Telling truth."); } else { log("Lying like a rug."); } } private static void log(String aText){ System.out.println(aText); } }
An example run of this class :
>java -classpath . BoxingExamples
Exploding 3 times.
Telling truth.
1989
1999
2004
intYear == integerYear: TRUE
integerYear.equals(intYear): TRUE
intYear == integerYear : FALSE
integerYear.equals(intYear): FALSE
See Also :
Would you use this technique?