Java's pseudo-closures
Jul 4, 2010       3:24 pm

The first of Sussman and Steele's "Lambda Papers" about Scheme in 1975 describes a closure as:

"... a data structure containing a lambda expression, and an environment to be used when that lambda expression is applied to arguments."

For someone who considers himself a language nerd, I find it surprising that it has taken me so long to get a strong handle on the definition of "closure". I've been further disappointed by the lack of understanding I've found among peers, particularly in discussions related to Java. I finally feel like I have sufficient knowledge to explain the relation of closures to Java.

I should note that, at the time of this writing, Java 7 has not yet been released, so I'm discussing Java 6.

Bound and unbound variables

I think the Wikipedia summary well reflects what most people think of when they think of closures:

"... a first-class function with free variables that are bound in the lexical environment."

I'm going to assume the reader understands all of these terms, but I'll illustrate with a quick JavaScript example:

var f = function() { 
  var a = 1;
  var g = function(x) { 
    var b = 2;
    return a + b + x;
  };
  return g(3);
} 

f() evaluates to 6.

The variables in g are x, a, and b.

  • b and x are defined within g.
  • a is a free variable within g. It is bound by a previous declaration within the same lexical scope as the declaration of g.

We call this expression of g a "closure" because it is "closed" (has its free variables bound) by its lexical environment.

Java: has closures?

Java obviously doesn't have first-class functions, but that doesn't stop the determined developer from pretending that it does with silly interfaces like these:

public interface NoArg<R> {
  R call();
}
public interface OneArg<A, R> {
  R call(A a);
}

Here's a trivial example in Scala, a beautiful language that does support closures:

def f(x:Int) = {
  () => { x }
}
val g = f(3)

g() evaluates to 3.

() => { x } is a first-class function with a free variable x. The return value of f is a closure.

We can do nearly the same thing in Java, albeit more verbosely:

public class A {

  public static NoArg<Integer>
      f(final Integer x) {

    return new NoArg<Integer>() {
      public Integer call() {
        return x;
      }
    };

  }

  public static NoArg<Integer> g = f(3);

}

A.g.call() evaluates to 3.

For a while, I actually tried to argue that Java does basically have closure support because you can do things like this. If we can convince ourselves that the NoArg instantiated in f(Integer) is effectively a function object, and it has a free variable x, then why can we not say that what f returns is a closure?

What Java cannot do

We're going to modify the example a bit:

def f(x:Int) = {
  var i = -1
  () => {
    i = i + 1
    x + i
  }
}
val g = f(3)

Repeated invocations of g return {3, 4, 5, ...}.

And now let's try it in Java:

public class A {

  public static NoArg<Integer>
      f(final Integer x) {

    int i = -1;

    return new NoArg<Integer>() {
      public Integer call() {
        i++;
        return x + i;
      }
    };

  }

  public static NoArg<Integer> g = f(3);

}

Javac balks at this code, however, with this complaint: "local variable i is accessed from within inner class; needs to be declared final". Indeed, this is consistent with the Java language specification:

"Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final. Any local variable, used but not declared in an inner class must be definitely assigned before the body of the inner class."

The rule makes sense, really. i lives on the stack, so we can't count on it still being there at some later time when g is called. We got away with the previous example because all free variables in the inner class (just x) were declared final, in which case Java is smart enough to immediately copy the value of x into the object when it is constructed.

Faking it

We can actually get around this. It's ugly, but by wrapping i in an object, we force it onto the heap:

public class A {

  private static class ValueHolder<T> {
    T value;
  }

  public static NoArg<Integer>
      f(final Integer x) {

    final ValueHolder<Integer> i =
      new ValueHolder<Integer>();
    i.value = -1;

    return new NoArg<Integer>() {
      public Integer call() {
        i.value++;
        return x + i.value;
      }
    };

  }

  public static NoArg<Integer> g = f(3);

}

Scala gives you "true" closures by doing this for you automatically, as Odersky et al. describes in Programming in Scala:

"The Scala compiler rearranges things in cases like this so that the captured parameter lives out on the heap, instead of the stack, and thus can outlive any method call that created it. Capture any variable you like: val, var, or parameter."

So, does Java have closures? Not really. But you can do anything if you're willing to do enough typing.

new comment >