Closures in Java 7.0

SHARE & COMMENT :

What is a closure?

Wikipedia says:

A closure is a function that is evaluated in an environment containing one or more bound variables.(Free variables which are to be passed to the function).In some languages closures may occur when a function is defined within another function and the inner function refers to the local variables of the outer function.At runtime when outer function executes, a closure is formed consisting of inner function’s code and references to any variables of the outer function required by the closure.

also read:

Functions behave as first class value in a closure supported programming language.It allows Functions to be passed as arguments,returned from the function calls,bound to variable names etc.

However as Neal pointed out that basic definition of closures is originated from the LISP Community. A closure is a function that captures the bindings of free variables in a lexical context.

Please refer to Neal’s blog for various lexical scoped language constructs in java.

What’s wrong with anonymous inner classes?

  • They cannot access non final variables in anonymous inner classes
  • Problem is that variable names are simply not resolved in the correct scope.They are resolved in the scope of anonymous inner class you are creating not the enclosing scopes.
  • Bit tedious to use in practice.

Let’s try to closely look into the specification for closures

Closure Literals

{ FormalParametersopt => BlockStatementsopt Expressionopt }

Evalution of the closure literal will result in closure instance which inturn will result to some object type.If it is not subject to closure conversion than it is converted to some function type of the closure literal with identical argument types;a return type that is the type of final expression if one exits or void or java.lang.Unreachable(New class to be introduced in jdk 1.7)

Example:

public static void main(String[] args) {
printClosure({=>"Hello World Closures From Prashant"});
}

static void printClosure({=>String} output) {
System.out.println(output.invoke("pras"));
}

Method accepts closure literal which does not take any parameters but returns a string.Please remember that all free lexical bindings(variables from enclosing scopes,this,break,continue,return) not defined within the closure literal are bound at the time of evalution of closure literal to their meaning in the lexical context in which closure literal appears.

Always remember break or continue statement in closure literal’s body may transfer to the matching enclosing statement.return statement always returns from the nearest enclosing method or constructor.

Below example shows usage of closures passing to methods.Please note that below example is heavily influenced by examples shown by Ricky Clarkson and Debasish

interface Animal {
 String getName();
 void description(String desc);
}

interface SwimBehavior {
 void swim();
}

interface FlyBehavior {
 void fly();
}

class FlyBehaviorImpl implements FlyBehavior {
 public void fly() {
  // TODO write impl for fly mechanism
 }
}

class SwimBehaviorImpl implements SwimBehavior {
 public void swim() {
  // TODO write impl for swim mechanism
 }
}

class Dog implements Animal
{
 public SwimBehavior swimBehavior;

 public String getName() {
  return "Dooooog";
 }

 public void description(String desc) {
  System.out.println("Description:" + desc);
 }

 public void setSwimBehavior(SwimBehavior swimBehavior) {
  this.swimBehavior=swimBehavior;
 }
}

public class PrintAnimalsClosure<A,D> {

 public final A a;
 public D d;

 public PrintAnimalsClosure(A a) {
  this.a=a;
 }

 public <U extends A> D getDescription(Class<U> u,{U=>D} closure) {
  if(u.isInstance(a))
  d=closure.invoke(u.cast(a));
  return d;
 }

 public void printDescription({=>Animal} anClosure,String desc) {
  Animal animal=anClosure.invoke();
  animal.description(desc);
 }

  public static void main(String args[]) {
  Dog dog=new Dog();
  dog.setSwimBehavior(new SwimBehaviorImpl());
  dog.swimBehavior.swim();

  PrintAnimalsClosure<Dog,String> pac=new PrintAnimalsClosure<Dog,String>(dog);
  String str=pac.getDescription(Dog.class,{Dog d=>"bow"});
  System.out.println("Desc:" + str);

  // 2nd way probably
  pac.printDescription({=>dog},"beow");
 }

}

Note internally when we compile this example a function type is translated to a system generated interface type.

The auto-generated-code is shown below which is similar for O and OO interfaces.

package javax.lang.function;

public interface OO
{
    public abstract Object invoke(Object obj)
        throws Throwable;
}

Interface name depends on the parameter and the return type arguments passed to the closure.

As we pass Object and retrieve Object as return type hence function name is OO.

Please remember that the body of a closure literal may not assign to a final variable declared outside the closure literal.

A new class called java.lang.Unreachable will be added in jdk 1.7.Variables of this type appear where statements or expressions cannot complete normally.Below example shows usage of Unreachable.

import java.lang.reflect.*;

class UnreachableDemo
{
 public static <T> T f() {
  return null;
 }

 public static void main(String[] args)
 {
  try
  {
   final int x;
   x=11;
   if(true) UnreachableDemo.<Unreachable>f();
   throw null;
  }
  catch (NullPointerException ex)
  {
   System.out.println("ok");
  }
 }

}

Also a syntantic form of Function Types are introduced.

What are Function Types?

A Function type describes a set of functions that accept a given argument types,result in a value of the given type,and may throw the exception.

Ex:
{int,int=>int} plus = {int x, int y => x+y};
int x1 = plus.invoke(1, 2);

Comments

comments

About Krishna Srinivasan

He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.

Comments

  1. Lambda expression allows the compiler to infer the type of the variable based on the context

Speak Your Mind

*

Close
Please support the site
By clicking any of these buttons you help our site to get better