It's perfect.
It's unbelievable.
It's a miracle
It's a TV dinner.
It's Fuwjax.

Email Twitter Facebook Google+ LinkedIn Github Stackoverflow Steam Youtube Creative Commons License

Closures in Java are always a ripe source for debate, discussion, flame wars, angst ridden blog posts about the joys of other languages etc. But we’ve been able to do something very near closures all along. First, the test:

public class WishfulTest{
  String greet = "hi";

  @Test
  public void test(){
    final String name = "Bob";
    <<< V = (){greet + " " + name} >>>
    assertThat(doSomething(<<< V >>>), is("howdy Bob"));
  }

  private String doSomething(<<< WishfulThing V >>>){
    greet = "howdy";
    String ret = <<< V.invoke() >>>;
    greet = "hola";
    return ret;
  }
}

There are 4 places in the above test that we just don’t really know how to fill in. The first is creating the closure. The next is passing it as a parameter. Then we have to accept it as an argument. Finally, we have to invoke the deferred object. Now, Java has always had some means of doing just this, namely, anonymous classes. They get the local context where they’re created, and they get an implicit reference to the “this” object where they were created. The problem is that they’re very bulky. So this example might use the following anonymous class:

public class WishfulTest{
  ...
  public void test(){
    ...
    Closure v = new Closure(){
      public String invoke(){
         return greet + " " + name;
      }
    };
    ...

I’ll leave the rest of the implementation to your imagination. But essentially, we must declare a method and a class to pass around a closure in Java.

Really, we just want the method. But methods aren’t first class objects in Java, only classes. So we have to have a class definition, there’s no way around it. Then can we ditch the method? The answer again is no. Java only associates code with methods. There’s just no escaping it in Java, if you want code, you must have a class and you must have a method.

You can cheat a little. You can stick your code in something called an initializer. An initializer is code that’s run with your constructor. Basically, you just throw your code into a block outside of any method and java creates an unnamed method. You can’t just call it whenever you want though, it will only be invoked during instantiation.

That doesn’t really buy us much, does it? Anonymous classes are instantiated as they’re declared, so you can’t defer the initialization. Inner classes are great, but they don’t pick up the method state if you declare them in the class body. But it turns out that there’s a tiny little feature that is generally completely useless. You can declare classes in your methods. They aren’t visible outside the scope, so you can’t generally do anything with them, but here’s that example again.

public class WhenUsingFunky{
  String greet = "hi";

  @Test
  public void test(){
    final String name = "Bob";
    class V extends Funky<String>{&#123;ret = greet + " " + name;&#125;}
    assertThat(doSomething(V.class), is("howdy Bob"));
  }

  private String doSomething(final Class<? extends Funky<String>> cls){
    greet = "howdy";
    final String ret = Funky.invoke(this, cls);
    greet = "hola";
    return ret;
  }
}

So essentially our closure is a Class instance. By using an initializer (notice the double curly brace) we effectively declare a constructor which sets an instance variable named “ret” to the concatenation of the WhenUsingFunky.greet field and the final local variable named “name” in the declaring method. But this code does not execute until the Funky.invoke line in the doSomething method. Which means that instead of picking up the value of “greet” set in the declaration, it uses the latest value at the time of the invoke call.

Funky itself is a fairly simple class. Here’s the gist of it:

public class Funky<T>{
  public static <T> T invoke(final Object self, final Class<? extends Funky<T>> cls){
    try{
      final Constructor<? extends Funky<T>> c = cls.getDeclaredConstructor(cls.getEnclosingClass());
      return c.newInstance(self).ret;
    }catch(final Exception e){
      throw new RuntimeException(e);
    }
  }

  public T ret;
}

So we grab the constructor that is generated by the compiler for non-static inner classes. Then we create a new instance using the supplied value as the target. The constructor should be accessible (though it’s fun to try to figure out why) even though the class V itself is not visible outside the declaring method. The field ret is public since if it were private, then V couldn’t set it in its initializer, and if it were protected or default access, the invoke method couldn’t see it (though again, it’s fun to try to figure out why). It doesn’t hurt encapsulation much though, since the only instances of V exist for a short time just inside the invoke method itself.

So, there you have it. A very concise, horribly complex syntax for declaring closures. The next step is to try to pass parameters to the invoke method, that should be fun.


Posted with : De Machina