What are closures in java

The Beauty of Closures

Most articles about closures are written in terms of functional languages, as they tend to support them best. However, that’s also precisely why it’s useful to have an article written about how they appear more traditional OO languages. Chances are if you’re writing in a functional language, you know about them already. This article will talk about C# (versions 1, 2 and 3) and Java (before version 7).

What are closures?

To put it very simply, closures allow you to encapsulate some behaviour, pass it around like any other object, and still have access to the context in which they were first declared. This allows you to separate out control structures, logical operators etc from the details of how they’re going to be used. The ability to access the original context is what separates closures from normal objects, although closure implementations typically achieve this using normal objects and compiler trickery.

It’s easiest to look at a lot of the benefits (and implementations) of closures with an example. I’ll use a single example for most of the rest of this article. I’ll show the code in Java and C# (of different versions) to illustrate different approaches. All the code is also available for download so you can tinker with it.

Example situation: filtering a list

It’s reasonably common to want to filter a list by some criterion. This is quite easy to do «inline» by just creating a new list, iterating over the original list and adding the appropriate elements to the new list. It only takes a few lines of code, but it’s still nice to hide that logic away in one place. The difficult bit is encapsulating which items to include. This is where closures come in.

Although I’ve used the word «filter» in the description, it’s somewhat ambiguous between filtering items in the new list and filtering things out. Does an «even number filter» keep or reject even numbers, for instance? We’ll use a different bit of terminology — a predicate. A predicate is simply something which matches or doesn’t match a given item. Our example will produce a new list containing every element of the original list which matches the given predicate.

In C# the natural way of representing a predicate is as a delegate, and indeed .NET 2.0 contains a Predicate type. (Aside: for some reason LINQ prefers Func ; I’m not sure why, given that it’s less descriptive. The two are functionally equivalent.) In Java there’s no such thing as a delegate, so we’ll use an interface with a single method. Of course we could use an interface in C# as well, but it would be significantly messier and wouldn’t let us use anonymous methods and lambda expressions — which are precisely the features which implement closures in C#. Here are the interface/delegate for reference:

Читайте также:  Unity c или java

// Declaration for System.Predicate public delegate bool Predicate(T obj) // Predicate.java public interface Predicate

The code used to filter the list is very straightforward in both languages. I should point out at this stage that I’m going to steer clear of extension methods in C# just to make the example simpler — but anyone who has used LINQ should be reminded of the Where extension method. (There are differences in terms of deferred execution, but I’ll avoid those for the moment.)

// In ListUtil.cs static class ListUtil < public static IListFilter(IList source, Predicate predicate) < Listret = new List(); foreach (T item in source) < if (predicate(item)) < ret.Add(item); >> return ret; > > // In ListUtil.java public class ListUtil < public static List filter(List source, Predicate predicate) < ArrayListret = new ArrayList(); for (T item : source) < if (predicate.match(item)) < ret.add(item); >> return ret; > > 

(In both languages I’ve included a Dump method in the same class which just writes out the given list to the console.)

Now that we’ve defined our filtering method, we need to call it. In order to demonstrate the importance of closures, we’ll start with a simple case which can be solved without them, and then move on to something harder.

Источник

Java Closures

In this article, I will explain what a closure is and clear the confusion surrounding anonymous inner classes and closures, then java’s current situation with respect to closures.
First I want to emphasize the below two points:

  1. As of JDK 1.6 we don’t have closures in java.
  2. Annonymous inner classes in java are not closures.

Definition of closure

Function types and inline function-valued expression are called closures. Let me decrypt this definition for you. An anonymous function that contains some context surrounding it as a snapshot and can be passed as a parameter. This closure defintion has two parts. First one is about callback. That is, a pointer to a function that can be passed as a parameter. Second part of the definition is, this callback function will enclose some contextual information surrounding it as a snapshot and passed along with the function.

Читайте также:  Php transparent background color

A closure is also referred to as a ‘first class object’ which can refer to attributes from its enclosing scope. As defined by Christopher Strachey in ‘Understanding Programming Languages’, a first class object can be stored in a data structure, passed as a parameter, can be returned from a function, can be constructed at runtime and independent of any identity.

In case if you are curious in Mathematics a closure is, when you operate on a members fo a set and if the resultant is always a member of that set then its called a closure.

Anonymous inner class is not closure

Anonymous classes in java are close to being called as a closure. They don’t 100% support the definition but come close to it and thats why we see lot of literature calling anonymous inner classes as closure. Why do I say its not 100%? An anonymous inner class can access “only” the final local variable of the enclosing method. It is because of this restriction, anonymous inner class in java is not a closure.

If you remember the memory management in java, you can recall that the local variables are stored in a stack. These java stacks are created when the method starts and destroyed when it returns. Unlike local variables, final fields are stored in method area which lives longer even after the return of the method. If we want to make anonymous inner class as a closure, then we should allow it to access all the fields surrounding it. But, as per the current memory management, they will be destroyed and will not be accessible after the method has returned.

Closure in Java

In that case will we get closure in java in future? We have a specification written by Peter Ahe, James Gosling, Neal Gafter and Gilad Bracha on closures for java. It gives detailed description of how a closure can be implemented in java and example code on how to use them. We have JSR 335 for closures in java named as Lambda Expressions for the Java Programming Language.

Источник

Java closure

Before you can learn the concept of closures, you need to understand the concept of free variables. Free variable: a variable not declared in the current scope. (that is, variables declared in other scopes)

Public class Demo1 >Copy the code

The x used by res in the above code is not defined in f1(), where x is a free variable.

1.2 Java inner Classes

1.2.1 Definition of inner classes

Java inner classes define another class inside a class. The inner class references the variables of the outer class through this. And inner classes need to be attached to outer classes to exist. The inner class object is created using.new of the outer class object.

public class Outer < private int y = 5; private class Inner < private int x = 10; public int add() < return x + y; >public Outer getOuter()< return Outer.this; >>>Copy the code

Here, the add method in the Inner class Inner holds the free variable X of the Inner class’s scope, forming a closure.

1.2.2 The role of inner classes

The biggest function of inner class is that each inner class can inherit a parent class, realizing multiple inheritance of classes.

public class TestClass extends AbstractFather < @Override public String sayHello() < return fatherName; >class TestInnerClass extends AbstractMother < @Override public String sayHello() < return motherName; >>>Copy the code

AbstractFathor and AbstractMother both contain the sayHello method.

1.2.3 Classification of inner classes

public class Parcel5 < public Destionation destionation(String str)< class PDestionation implements Destionation< private String label; private PDestionation(String whereTo)< label = whereTo; >public String readLabel() < return label; >> return new PDestionation(str); > Copy the code
  1. Static inner classes: A static inner class is a static inner class. The main difference between a static inner class and a normal member inner class is that the static inner class has no reference to the enclosing class. Therefore, its creation does not depend on the enclosing class, but it cannot use any non-static member variables and methods of the enclosing class.
public class Singleton < private static class SingletonHolder < private static final Singleton INSTANCE = new Singleton(); >private Singleton ()<> public static final Singleton getInstance() < return SingletonHolder.INSTANCE; >>Copy the code

The biggest use of static classes is to create thread-safe singleton patterns.

  1. Anonymous inner classes: Anonymous inner classes are unnamed inner classes that are often used when we need to quickly create multiple threads:
new Thread(new Runnable() < @Override public void run() < System.out.println("hello"); >>).start(); Copy the code

Anonymous inner classes have no access modifiers and no constructors. An anonymous inner class exists attached to an interface and cannot be created if the implemented interface does not exist. If an anonymous inner class accesses a free variable of its method, that free variable is final.

1.3 Java closures

Closures consist of a function + reference environment. True closures move the variable referenced by a function into heap memory when the variable is on the stack and assign the reference to it. Because Java is value passing and does not support reference passing, a Java closure counts as a half-closure. Java handles referenced free variables by copying the value into a function.

Источник

Оцените статью