abstraction that fits the collection type. If the size is fixed and you need to fre-
quently enumerate the collection, an array could be the best choice.
Because arrays can have a significant effect on memory, they warrant special
consideration. These tips can help:
If you have many collections with widely varied size, consider another
collection that allocates dynamically.
Delay initialization (and thus allocation) until the automatic variable is
If the array is sparse, it should be declared appropriately. You shouldn't
create methods (such as accessors) that you don't plan to use.
We have all seen excruciatingly complex object hierarchies with inheritance
chains that reach all the way to China. Similarly, just as databases can be nor-
malized too far, object-oriented design can be taken to extremes beyond any-
thing that can practically perform. If you aren't in a memory-constrained
environment, let common sense be your guide. On the other hand, as inherit-
ance chains get longer, the memory cost is higher. If memory is a serious con-
cern and other avenues have been exhausted, reducing the length of
inheritance chains can save some valuable memory. This practice should never
compromise reuse, design principles, or readability, but when considering
whether to add one more subclass, you'll find that memory can be a tiebreaker.
Let's clean up this chapter by reviewing what we have covered and presenting
our antipattern templates. We began by discussing memory-management phi-
losophies of C ++ and Java. We presented the old and new strategies of garbage
collection, and showed that Java garbage collection is based on a concept
called reachable objects. We then showed that even Java is prone to memory
leaks, and we described general symptoms and specific antipatterns called
Lapsed Listeners, Leak Collections, and Little Hogs. Finally, we examined
common strategies that you can use to shoot down memory leaks, and looked
at some “little hogs” that can make a big cumulative impact.