Closures - yes, Java has them!
rzwitserloot posted in programming on November 25th, 2006
Martin Fowler suggests java doesn’t have true closures, then shows a bunch of examples. In order to try help this discussion along a bit, I’ll eliminate Fowler’s attempt at FUD and write every single one of his examples in java code. Note that aside from a bunch of lies (specifically regarding closing over lexical scope - something java closures a.k.a. anonymous classes also do eventhough Fowler’s suggests otherwise) he also suggests they are wordy. This is true. Support CICE, a proposal to shorten the wordiness considerably without losing any expressiveness or adding complexity to the language!
The rewritten examples are after the jump.
ruby:
def managers(emps)
return emps.select {|e| e.isManager}
end
Same thing in current 1.5 java:
public List<Employee> managers(List<Employee> employees) {
return Collections.select(employees, new SelectFunction<Employee>() {
public boolean select(Employee e) {
return e.isManager();
});
}
}
The ’select’ function doesn’t actually exist yet (java can do it, but sun doesn’t think anyone would want to,
but it’s a 3-liner if you want it in. Again, legal java 1.5 code:
public static <T> List<T> select(List<T> list, SelectFunction<T> selector) {
List<T> result = new LinkedList<T>();
for ( T t : list ) if ( selector.select(t) ) result.add(t);
return result;
}
public interface SelectionFunction<T> {
boolean select(T t);
}
if the CICE proposal
is accepted, the wordiness of using java’s closure (anonymous classes) virtually disappears:
public Collection<Employee> managers(Collection<Employee> employees) {
return Collections.select(employees, SelectFunction(Employee e) {
return e.isManager();
});
}
There is the unfortunate ‘Collections’ tidbit (instead of just employees.select()) but campaigning for an elegant solution there is for another day.
Ruby:
def highPaid(emps)
threshold = 150
return emps.select {|e| e.salary > threshold}
end
java (+CICE):
public boolean highPaid(List<Employee> employees) {
final int treshold = 150;
return Collections.select(employees, SelectFunction(Employee e) {
return e.getSalary() > treshold;
});
}
(NB: CICE can be automatically ‘rewritten’ to a currently legal anonymous class declaration. Its only use is eliminating wordiness, it’s just syntactic sugar. I use CICEd java here because I like CICE and I want the word the spread).
ruby:
def paidMore(amount)
return Proc.new {|e| e.salary > amount}
end
java (+CICE):
public SelectFunction<Employee> paidMore(final int amount) {
return SelectFunction(Employee e) {
return e.getSalary() > amount;
};
}
which would allow you to do tricks like:
john = new Employee("John");
john.setSalary(200);
SelectFunction<Employee> highPaid = paidMore(150);
System.out.println(highPaid.select(john));
ruby:
File.open(filename) {|f| doSomethingWithFile(f)}
java in the file class:
public void operate(FileOperation oper) {
InputStream is = new FileInputStream(this);
try {
oper.run(is);
} finally {
try {is.close();} catch (Exception ignore) {}
}
}
public interface FileOperation {
void run(InputStream reader) throws Exception;
}
Once the above exists, you can do (with CICE):
new File(filename).operate(FileOperation(BufferedReader reader) {
doSomethingWithStream(is);
});
A notation here: java abstracts files more than ruby does;
a File object is merely a fancy wrapper around strings. A file object
itself never opens files and you can make file objects to non-existant
files. Thus ‘doSomethingWithFile’ is fundamentally not applicable to java
io design philosophy. The nearest relative is the more generic ‘doSomethingWithStream’,
which is what has been used in these examples.
Note how aside from typing information (which is a wholly separate discussion) the java
examples don’t really add many more characters to the example code. In other words, java
certainly does have closures.

February 2nd, 2007 at 17:57
[…] Closures - yes, Java has them! […]