Another way of putting it is a closure is an anonymous function body, that can be declared and passed around as a first-class object and which can refer to variables from its enclosing scope. The anonymous classes in JDK (Java Development Kit) 1.1 provide closure-like facilities, albeit with tacky syntax. Smalltalk blocks are closures.
Allen Wirfs-Brock of Instantiations (the Jove people) explains them this way: Closures relate to the life-time of local variables (and parameters). In Java, any time a method is called, a new set of the method’s local variables (and parameters) are allocated upon the stack. For purposes of discussion we will call the specific set of local variables associated with a particular activation of a method the environment of that activation. For Java, an environment is typically implemented as a stack allocated activation record. When a method returns, the environment associated with the current activation is discarded. This is why you can have multiple activation of a method (for example a recursive method) and each activation has its own private set of local variables.
A closure is an object that associates a block of code (which is nested within a method) with the current environment of the enclosing method such that if the block of code is evaluated at a latter time any references from within the block to local variable of the enclosing method will access the instance of the local variables in the associated environment.
Why would you want to do this. Because sometimes it is very useful to parameterize an algorithm with an open ended piece of code. Consider for example, a sort algorithm which at it’s core needs to compare two objects to determine their relative ordering. If the comparison function is a parameter to the sort method then a single copy of the sort algorithm can be used with a wide variety of data types.
If Java had closures, what would they look like? How about exactly like an anonymous inner class. In fact, consider this statement from the JLS (Java Language Specification) 2nd ed. p. 141: Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final and must be definitely assigned before the body of the inner class Without this restriction, an inner class would essentially be a closure! Any time you use Java anonymous inner class you are using a restricted form of closure.
So, why does this restriction exist? This restriction essentially says that an inner class can only access outer local variables whose final values are known at the time the inner class is instantiated. Consider that it is possible for an instance of an inner class to continue to exist after the method that created it returns (for example, it might be stored into a static field). What would happen if such an inner class references a local variable of the enclosing method. With a stack based environment the activation record containing the variable may have already been discarded and over-written. Things could break badly! The JLS restriction means that it is ok for the Java implementation to copy the values of such local variables into instance variables of the inner class and convert any reference to such a local variable from the code of the inner class into a reference to the instance variable. Because the values are in instance variables there is no need to worry about whether the original activation record has been discarded.
This trick only works with constant (i.e. final) values. It doesn’t work for variables whose modification need to be visible to both the inner class and the enclosing method because a change to a copy wouldn’t be visible to the original. In order to eliminate the JLS restriction, it would be necessary to heap allocated (and garbage collection) the activation records (or at least the portion containing any such variables) of such methods.
The JLS restriction presumably exists for efficiency reasons as heap allocated activation records are commonly believed to be inefficient. In fact, implementors of languages with closures know many tricks for avoiding these inefficiencies and it would be quite possible to efficiently implement them without any changes to the JVM (Java Virtual Machine) specification or implementation. The work would all be in the bytecode compiler. Take the above JLS restriction away and Java would have closures.
This page is posted
Optional Replicator mirror
|no blog for this page||Canadian
Your face IP:[188.8.131.52]
You are visitor number|