On Closures in Java
While reviewing Martin Fowlers upcoming DSL book I started thinking (again) about closures in Java and the current overly verbose syntax for Single Abstract Method Interfaces. And then there was the blog entry of Anders NorĂ¥s about Deferred Execution and Kicker Methods, both relaying to the DSL stuff I just read.
So starting with a SAM closure.
new Closure() { public Integer eval() { return input.length(); } } closure.eval();
So I thought about the Java Instance Initializer Block, which is executed before the constructor is called.
class A {
{
initializer code;
}
... constructor and class body ...
}
So, combining the Anonymous inner class with the initializer Block gave me.
new Closure() {{ result=input.length(); }} closure.result
the problem is that the code there is evaluated when defining the class and creating the anonymous instance, so there is no deferring possible.
Using a SuperClass for the closure which basically does this.
class Closure{ public R eval() { return newInstance().result; } private Closure newInstance() { try { final Constructor syntheticConstructor = getClass().getDeclaredConstructors()[0]; return (Closure ) syntheticConstructor.newInstance(createParams()); } catch (Exception e) { throw new RuntimeException("Error creating new instance of closure", e); } private Object[] createParams() throws IllegalAccessException { final Field[] fields = getClass().getDeclaredFields(); final int fieldCount = fields.length; final Object[] params = new Object[fieldCount]; params[0] = fields[fieldCount - 1].get(this); // enclosing Instance comes last for (int i = fieldCount - 2; i >= 0; i--) { params[i + 1] = fields[i].get(this); } return params; } } }
I didn’t think so but it is possible to create additonal new Instances of Anonymous Inner Classes, you just have to watch for the synthetic constructor and the reference to the enclosing class. If you don’t use constructor parameters to pass into the closure, you’ll have to support all the referenced final outer variables, so passing parameter is certainly more useful.
so the result is:
new Closure() {{ result=input.length(); }} assertEquals(10,closure.eval());
to reduce noise one can skip the generics and cast the types accordingly.
non final input data can be done be creating a constructor in the closure which takes vararg arguments of declared generic types and
keeps them in protected final fields for reuse in the expression block;
The remaining problem is that one has to use non primitive Objects as integrated final local variables.
I put the complete code on my website.

