Seven Low-Cost Ways to Improve Legacy Code
Pages: 1, 2
6. Replace Listeners with Weak Listeners
Chapter 11 ("References in Four Flavors") of Hardcore Java illustrates a recurring problem in many Java programs, namely the creation of circular reference trees that pin objects in memory and interfere with garbage collection. The widely held misconception that a "Java developer does not have to worry about the memory of his program" has led many Java developers to create programs that require excessive amounts of resources. The extra resources consumed by objects unintentionally pinned in memory are Java's version of a memory leak.
This kind of memory leak can be avoided by the use of weak references and weak listeners. Weak references are a special kind of reference that do not block garbage collection. This allows your data objects to hold references to GUI panels in their property change listeners without blocking the garbage collection of those panels. Furthermore, it relieves the user of the data object from having to constantly manage the addition and removal of listeners, which results in code that is easier to manage. Legacy programs can be easily converted to use weak listeners. To show how these programs can be converted, consider the following legacy code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SomeButtonClass1 {
private final Set listeners = new HashSet();
public void addActionListener(final ActionListener l) {
listeners.add(l);
}
public void removeActionListener(final ActionListener l) {
listeners.remove(l);
}
protected void fireActionPerformed(final ActionEvent event) {
for (final Iterator iter = listeners.iterator();
iter.hasNext();) {
((ActionListener)iter).actionPerformed(event);
}
}
}
This code can easily be converted to use weak listeners with a couple of minor changes:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
public class SomeButtonClass {
private final Map listeners = new WeakHashMap();
public void addActionListener(final ActionListener l) {
listeners.put(l, null);
}
public void removeActionListener(final ActionListener l) {
listeners.remove(l);
}
protected void fireActionPerformed(final ActionEvent event) {
for (final Iterator iter = listeners.keySet().iterator();
iter.hasNext();) {
((ActionListener)iter).actionPerformed(event);
}
}
}
After these three small changes, the listeners don't even need to bother with removing themselves, if they don't wish to. If they remove themselves, all will be OK. If they are merely garbage collected, all will still be OK. To understand how this works in more detail, I encourage you to read Chapter 11 of Hardcore Java.
|
Related Reading Hardcore Java |
7. Replace Integer Constants with Constant Objects or Enums
Chapter 7 ("All About Constants") of Hardcore Java talks about constants in detail. One of the most important lessons you should carry out of that chapter is that using integers for option constants is a bad idea. For example, if you want to create a class that can only take a color of the rainbow as an argument to a method, using integers for each of the seven colors is the wrong approach. We show an example of such code here:
public final class RainbowColor {
public final static int RED = 0;
public final static int ORANGE = 1;
public final static int YELLOW = 2;
public final static int GREEN = 3;
public final static int BLUE = 4;
public final static int INDIGO = 5;
public final static int VIOLET = 6;
}
When using integer constants such as these, you might write the following code:
public void doSomething(final int rainbowColor) {
// ...
}
The problem here is that the user can pass you any integer. In order to make solid code, you will have to check that integer in every piece of code against the valid integers. This checking code will have to be maintained in several places. On the other hand, the use of Enums or Constant Objects relieves you of the need to check, as we see in the revised option constant class:
public final class RainbowColor {
public final static RainbowColor RED = new RainbowColor("RED");
public final static RainbowColor ORANGE = new RainbowColor("ORANGE");
public final static RainbowColor YELLOW = new RainbowColor("YELLOW");
public final static RainbowColor GREEN = new RainbowColor("GREEN");
public final static RainbowColor BLUE = new RainbowColor("BLUE");
public final static RainbowColor INDIGO = new RainbowColor("INDIGO");
public final static RainbowColor VIOLET = new RainbowColor("VIOLET");
final String name;
private RainbowColor(final String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
With the revised class, no checking is necessary during its use:
public void doSomething(final RainbowColor rainbowColor) {
// ...
}
Since the user cannot create any more instances of the RainbowColor, there is
no need to check anything. Furthermore, since comparisons of the objects are
done by instance instead of by equality, comparisons are extremely fast.
If you have access to JDK 1.5 in your coding environment, enums are the
equivalent of Constant objects, with less code needed from the developer. If you
are stuck writing for an earlier JDK (as many corporate programmers are), you
should investigate and use the Constant object pattern extensively.
Conclusion
These seven techniques are fairly low cost in terms of man hours, and all are cost-free in terms of equipment and software. They can all be performed by hand or with freely available software. Although they represent only the tip of the iceberg of code-quality improvement, they offer a good place to start when time is tight and quality demands are high. Given the tools at the disposal of software engineers, there should be no excuse for writing code that is anything other than solid as stone. This will allow you to concentrate less on finding little annoying typos and more on the business your customers or employers use to make money. They will be happier with your code, and you will have to work less to accomplish the same tasks.
Robert Simmons, Jr. lives and works as a senior software architect in Germany. He is the author of O'Reilly's Hardcore Java.
O'Reilly Media recently released Hardcore Java.
Chapter 2, "The Final Story," is available for free online.
You can also look at the Table of Contents, the Index, and the full description of the book.
For more information, or to order the book, click here.
Return to ONJava.com.
-
Enums and "Constant Object"
2004-10-28 07:39:21 dubwai [View]
-
#8
2004-10-08 14:53:53 glenpepicelli [View]
-
Heuristics vs Rules
2004-06-09 14:57:57 Kevin O'Neill [View]
-
Re: Use a Stronger Compiler for Your Code
2004-06-02 01:53:13 L [View]
-
Re: 5: Removing Anonymous Inner Classes
2004-05-31 11:43:53 Ian F. Darwin |
[View]
-
Removing commented out code
2004-05-09 16:59:23 BrianHanafee [View]
- Trackback from http://davew.typepad.com/42/2004/05/onjavacom_seven.html
ONJava.com: Seven Low-Cost Ways to Improve Legacy Code [Apr. 28, 2004]
2004-05-07 00:41:09 [View]
-
Replace Listeners with Weak Listeners
2004-05-06 01:16:20 ipreuss [View]
-
PMD and jEnum
2004-05-03 08:57:48 stinkyminky [View]
-
JLint
2004-04-30 07:56:51 rasmusmc [View]
-
final checks
2004-04-29 07:28:12 simonharris1 [View]
-
using final with Serializable classes
2004-04-29 00:58:42 andyp [View]
-
IntelliJ IDEA
2004-04-28 19:39:49 michaelcherichetti [View]
