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.