Saturday, August 8, 2009

Anonymous Inner Classes: A Poor Man's Closure?


Yesterday I had a discussion with a colleague about whether Java has closures or not. We both could immediately agree that, formally speaking, Java does not have them, but the part of the discussion that went on and on was about passing anonymous inner classes vs. passing around an anonymous function. I argued that the anonymous inner classes were a very poor substitute because a class has so much extra baggage, both conceptually and behaviorally. Classes understand and do all sorts of things that you don't care about when you are simply trying to pass along a little ol' function. Stuff like: inheritance, encapsulation, polymorphism. Worst of all, classes require lots of messy syntax. My colleague made an important point though: What else is a Java developer gonna do? When you are working in Java and you need something like a closure you've got no choice but to go for the anonymous inner class, the poor man's closure.

Google's Collection Framework is the best example I know of Java programmers making do with their poor man's closures. Here is a quick bit of sample code I created that demonstrates applying a function to every element of a list (Sorry you can't see my generics. I can't seem to escape properly for html):


import com.google.common.collect.Lists;
import com.google.common.base.Function;
import java.util.ArrayList;
import java.util.List;
public class PoorMansClosure{
public static void main(String[] args){
//Demonstrate something similar to the map function on a collection in ruby
ArrayList strings = Lists.newArrayList("feeling", "bad");
Function upcase = new Function(){
public String apply(String from){
return from.toUpperCase();
}
};
List upperCaseStrings = Lists.transform(strings, upcase);
for(String val : upperCaseStrings){
System.out.println(val);
}
}
}

Martin Fowler has a nice article about how closures naturally compliment collections. Here is a quick bit of ruby to demonstrate that.

class Closure
def demonstrate
strings = ["feeling", "good"]
upper_case_strings = strings.map{|elem| elem.upcase }
p upper_case_strings
end
end
Closure.new.demonstrate


In this example the closure frees us from the burden of specifying the names and signatures for both class and method and we simply give the function that maps to upper case without the noise. There have been rumblings in the Java world for some time that Java might someday support closures. Here's hoping that Java 7 will. If that does happen it will be interesting to see what they do to the collection framework. The existance of Google's collection framework is proof that the standard Java framework has major drawbacks. I think a major rewrite will be in order.

6 comments:

Moandji Ezana said...

I'm pretty sure closures have been decisively dropped from Java 7. For example: http://www.infoq.com/news/2009/01/java7-updated

The real problem with inner classes for collections is that they're generally *less* readable than the for loops they replace. I'm sick to death of writing those loops, but inner classes are too little an improvement to justify the inevitable double-take every other dev on the project will do.

Unknown said...

I've come to rely heavily on closures in C# since 3.0. Recently been learning Java and the anonymous inner class pattern is unbearably clunky by comparison.

Shlomo said...

Moandji,

Thanks for that link. That is really, really, really bad news.

Moandji Ezana said...

Yeah. I'm convinced the Java language is pretty much stuck, due to the cult of retro-compatibility, unless Project Jigsaw somehow magically resolves that issue.

Anonymous said...

Interesting discussion, I knew about closures in Javascript but didn't know much about anonymous inner classes.

This page was a good reference too:


anonymous class in java example

Unknown said...

It's important to distinguish between 'closures', 'function literals', and 'first class functions'. This article seems to be more about function literals and first class functions than about closures.