It is often
appropriate to reuse a single object instead of creating a new functionally
equivalent object each time it is needed. Reuse can be both faster and more
stylish. An object can always be reused if it is immutable
(Item 15).
As an extreme
example of what not to do, consider this statement:
String s = new String("stringette"); // DON'T DO THIS!
The statement
creates a new String instance each
time it is executed. The argument to the String
constructor
("stringette") is itself a String instance
The improved
version is simply the following:
String s = "stringette";
You can often
avoid creating unnecessary objects by using static
factory methods (Item 1) in preference to constructors on
immutable classes that provide both. For example, the static factory method Boolean.valueOf(String).
you can also
reuse mutable objects if you know they won’t be modified.
// DON'T DO THIS!
public boolean isBabyBoomer() {
// Unnecessary allocation of expensive object
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >= 0 &&
birthDate.compareTo(boomEnd) < 0;
}
The isBabyBoomer method unnecessarily creates a new Calendar, TimeZone, and two Date instances each time it is invoked.
static {
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0
&&
birthDate.compareTo(BOOM_END) < 0;
}
If the
improved version of the Person class is
initialized but its isBabyBoomer method is
never invoked, the BOOM_START and BOOM_END fields will be initialized unnecessarily. It
would be possible to eliminate the unnecessary initializations by lazily initializing these fields (Item 71)
the first time the isBabyBoomer method is
invoked, but it is not recommended.
keySet method of the Map
interface
returns a Set view of the Map object, consisting of all the keys in the
map. Naively, it would seem that every call to keySet
would
have to create a new Set instance, but every call to keyset on a given Map
object
may return the same Set instance. Although the returned Set instance is typically mutable, all of the
returned objects are functionally identical.
There’s a new
way to create unnecessary objects in release 1.5. It is called autoboxing.
// 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);
}
Prefer
primitives to boxed primitives, and watch out for unintentional autoboxing.
Conversely,
avoiding object creation by maintaining your own object
pool is
a bad idea unless the objects in the pool are extremely heavyweight. The
classic example of an object that does justify an
object pool is a database connection. The cost of establishing the connection
is sufficiently high that it makes sense to reuse these objects.
Reference: Effective Java 2nd Edition by Joshua Bloch