July 19, 2005

Another reason why Lists beat Arrays and Generics are useful

Here's one of many reasons why Java generics do not suck: With generics we may finally forego arrays[] in favour of the List, which will ultimately make all of us better people. Not only can Lists grow and shrink on demand, they can also be smart about managing their own contents, and do not need a container to do it for them.

Say you're writing a class that holds a set of EventListeners and offers public methods to manipulate that set. This is the sort of clutter we used to produce for that simple job:

List eventListeners = new ArrayList();

public EventListener[] getEventListeners() {
    return (EventListener[])eventListeners.toArray();
}

public void addEventListener(EventListener el) {
    eventListeners.add(el);
}

public void removeEventListener(EventListener el) {
    eventListeners.remove(el);
}

Repeat that for any multiplicity-many reference in your code and you know where these line counts are going. Now that we have typesafe collections, we only need one method that might as well return our actual List:

List<EventListener> eventListeners = new ArrayList<EventListener>();

public List<EventListener> getEventListeners() {
    return eventListeners;
}

Should we later need to run funky code whenever a new EventListener is added, we can make our List aware of that:

List<EventListener> eventListeners = new ArrayList<EventListener>() {
    public boolean add(EventListener el) {
        super.add(el);
        // funky code goes here!
    }
};

I actually do not use ArrayList for a job like this, but a custom implementation of List that can only be manipulated using add and remove and throws an UnsupportedOperationException in response to anything else.

Because the returned List is an actual object we may pass it on to other methods, which can manipulate it without knowledge of the containing class. This alone allowed me to remove several pages of code today.

Arrays. What have they ever done for you? Switch to Lists and join me in parameterized Nirvana.

July 9, 2005

Heavy Java interfaces

There's one thing I never realized about Java until recently: You are allowed to go crazy with nesting. Say you have a simple interface:

public interface Interface {
    public void foo();
}

You could now nest an implementation of that inside the interface and make that implementation available in a singleton-ish fashion, all in the same file:

public interface Interface {

    public void foo();

    public class InterfaceImpl implements Interface {
        public void foo() { }
    }

    public static Interface INSTANCE = new InterfaceImpl();

}

You may now write Interface i = Interface.INSTANCE. Let's make this look even more wrong and implement Interface on the fly:

public interface Interface {

    public void foo();

    public static Interface INSTANCE = new Interface() {
        public void foo() { }
    };
	
}

By now you should feel an urgent need to wash your hands.

Comments (0)

July 6, 2005

Lovely presentation on Enterprise Java

I want to recommend a recorded presentation on Effective Enterprise Java by a charming and often funny Ted Neward. In the presentation Ted takes a very high-level look at common mistakes and misunderstandings that occur when designing large systems.

He also talks about God's virtual machine and the issue of Soviet commandos storming your data center, and while he didn't go all the way and incorporated ninjas into his talk, I say it's definitely worth your time.

Comments (0)

July 2, 2005

Generics Wildcards for Dummies

When you have a class Fruit and a subclass Cherry you might be surprised that in Java a List<Cherry> is not an instance of List<Fruit>.

The reason for this is that List<Cherry> does not extend the interface of List<Fruit>, but makes it more narrow. Normally you can do all the things with an subclass instance that you can with an superclass instance, and then some. This is not the case here: You can add a Banana to a List<Fruit>, but not to a List<Cherry>. Therefore you cannot treat a list of cherries as a list of fruits because someone might try to stuff in a banana.

"But wait!", you'll say. "I can write List<? extends Fruit> instead!". The answer is yes... and no. While the bounded wildcard ? extends Fruit lets you view a list of cherries as a list of fruits, it is not the same as List<Fruit>. For instance, you cannot add any Fruit to a List<? extends Fruit>, because Java cannot resolve whether it might actually be looking at a List<Cherry>, which can only add cherries.

What we learned today: Generics make a great tool for more type safety, but for heavy use... bring a gun.

Comments (0)