Joshua gives several advices how to avoid creating unnecessary objects.
1. read and know the language (spec). (or reuse immutable objects)
I also see this statement
String s = new String("i do not know the language really well"); // to not do this
too often. As Strings are immutable object in the Java Language the statment above is nonsense and creates unnecessary objects. (even worse if it is used in a loop). So: read and know the language and know about immutable and hence reusable objects 2. classes should offer a "static factory method" (seem Item 1)
As a hint in their API to reuse immutable object, their should use Item 1 e.g. a classical example is
Boolean.valueOf(String) // cheap: reuse object
instead ofBoolean(String) // expensive: create new object
Also note that the javadoc of the latter version mentions, that using this ctor is expensive and the "static factory method" valueOf is preferred (and using this in eclipse you get the corresponding help immediately)3. reuse mutable objects if you know they won't be modified
Now I do not agree 100% with the _phrasing_ of this statement, because if they are really immutable, why not make them final and immutable directly ? (most of the time this works) Also how do you know that they will not be modified. What about the user and maintainer of your code ?
However the example with Date and Calendar clarifies the intend and the solution: Do not compute the values again each time you use them in a function if they do not change. Instead make them "static final" and put the computation of them into a "static { }" Block. Now instead of n computations you have now one at class initialization time. If the method is never invoked you have a little overhead, initalizing the "static final" members, but that could be eliminated with Item 71 "lazy initializing fields". However Item 71 should really only be used for very large and expensive objects as it has other drawbacks and only pays off in a few cases.
4. be aware that autoboxing (new since Java 1.5) can create unnecessary objects
e.g. a small typo (using Long instead of long) now can trigger autoboxing and unboxing. So: prefer primitives to boxed primitives (the pre 1.5 rule was also prefer primitive to their Object counterparts) and: watch out for unintentional autoboxing (e.g. the classical typoe Long instead of long).
FYI: is think this is a good thing to know about: there is currently no findbugs rule for this but you can turn on a warning in eclipse "Boxing and unboxing conversions" ;-) There are other usefull warning in that eclipse java compiler setting for coding errors...
General Points to be aware of:
There is always a trade of between clarity, simplicity or power of a programm and efficiency or performance optimization. It is not to say that efficient programs could be not simplistic (no no ;-).
Also modern JVM implementaions do their best to optimize object creation and reclamation.However you should watch out for unnecesaary objects.
I use also often a profiler to find unnecessary objects. This is not an adviced from the book, but in my experience I found a lot of Items 5 in current code bases but using a profiler and tracking down those places.
Now a more general question is: what IS an "unnecessary" object, (if you want to start a discussion ;-) because there are counter-examples where we created additional objects (maybe they are unnecessary ?) intentionally.
Examples are:
- pooled objects in EJB container or any other container infrastructre where you do not manage the object lifecycle on your own
- datastructures where you have some additional reserve of objects to perform efficiently in the long term e.g. in HashMap(int initialCapacity, float loadFactor) you can have a loadFactor which the corresponding javadoc talks about.
- if you look at optimizing your disk e.g. under windows you also need additional ressources (typically 1/3 of the disk) to run the diskoptimizer in forseeable time (but that is another story).
No comments:
Post a Comment