blog.onlysimpler.com

A blog... only simpler.

Closures in Java - 27 September 2006

There's been some talk recently about adding closures to the Java language. I've spent quite a bit of time writing Ruby code recently, and it's amazing how useful closures and code blocks can be. They're one of those things - once you know how to use them, you start noticing all kinds of places in your code that could be solved using closures. It's like when you learn a definition of a new word and suddenly you start hearing it in conversations everywhere.

It will be interesting to see how the proposal turns out, but unfortunately we'll have to wait until Java 7 to use them. Considering how many people still haven't made the move to Java 5, this could be a while for some. In the meantime, there are a number of hacks that you can use to provide similar functionality to a closure. In fact, Apache Commons Collections even has some built in classes that provide closure-like functionality.

But if you need something quick and dirty, this should do the trick.

First, define a simple interface to represent a closure:

public interface Closure {
    public void execute(Object o);
}

The next step is to create a method that calls the execute method of the closure. The following example iterates over a collection and calls the execute method on every object.

public static void execOnEach(Collection<?> collection, Closure closure) {
    for (Object o : collection) {
        closure.execute(o);
    }
}

Finally, we write some code that uses the closure interface to execute a block of code on every object in a collection. We do this by creating an anonymous instance of the closure.

This example uses a collection of StringBuffer objects. The first call to execOnEach() converts each buffer to upper case, while the second call reverses the contents of the buffers.

public static void main(String[] args) {

    Collection<StringBuffer> c = new ArrayList<StringBuffer>();
    c.add(new StringBuffer("abcdefg"));
    c.add(new StringBuffer("hijklmn"));
    System.out.println("c = " + c);

    // capitalise everything
    execOnEach(c, new Closure() {
        public void execute(Object o) {
            StringBuffer buffer = (StringBuffer) o;
            buffer.replace(0, buffer.length(), buffer.toString().toUpperCase());
        }
    });

    System.out.println("c = " + c);

    // reverse the strings
    execOnEach(c, new Closure() {
        public void execute(Object o) {
            StringBuffer buffer = (StringBuffer) o;
            buffer.reverse();
        }
    }); 

    System.out.println("c = " + c);
}

This is a pretty trivial example, but you get the idea.

link