Understanding the closures debate
- ️Tue Jun 17 2008
Does Java need closures? Three proposals compared
With three proposals vying for inclusion in Java 7, understanding closures and the arguments for and against their inclusion in the Java language is essential. In this article Angelika Langer and Klaus Kreft give us a detailed overview of the three proposals — BGGA, CICE, and FCM — discussing the pros and cons of each, where they differ, and how they compare. The authors also explain the arguments against adding closures to Java 7, and conclude with their insight into where this debate will lead in the year ahead.
Closures, also known as blocks, are far from new to computer science. They’re a standard feature in older languages such as Scheme, Smalltalk, and Lisp, and have more recently made their way into dynamic languages such as Ruby and Groovy. Closures are a natural fit for statically typed, functional Scala, and recently many have argued that they have a place in the Java language, too.
Many developers argue, conversely, that closures are a bad fit for the Java language. According to this camp, adding closures would be the proverbial “nail in coffin” for the already stuffed syntax of a language that tries to do too much. The end result: a hot debate, which has been making its way toward the JCP, and around the conference circuit and the blogosphere, for more than two years.
While the closures debate may seem best left to Java linguists, the inclusion of closures in Java 7 — or not — will ultimately affect anyone who writes Java code. In this article we provide an overview of the new functionality being proposed for the Java language. We start with a simple introduction to closures, then explain how each proposal would integrate them onto the Java language syntax. We also discuss each proposal’s cost in terms of complexity. We consider the issue of closure conversion — essential for backward compatibility with older programs — and then delve into one of the most controversial aspects of the BGGA proposal: control abstractions.
Throughout the article we compare the pros and cons of the functionality each proposal would bring to the Java language, using code snips to demonstrate their impact on the Java programming experience. We conclude with an overview of the arguments for and against closures, as well as some insight into where these discussions may lead us in the year ahead.
So, what are closures?
Essentially, a closure is a block of code that can be passed as an argument to a function call, which will execute the block immediately or some time later. To some extent, a closure is similar to an unnamed (or anonymous) function. There is more to it, but for the time being, let us stick to this definition.
To better understand the purpose of closures, consider a simple example of a situation where you would want to pass a block of code to another function for repeated execution: a method forEach
that takes a sequence of objects is supposed to apply a given functionality to every object in the sequence. How would you pass the functionality to the forEach
method? Today in Java, you would have to define an interface, say Block
, and pass implementations of that interface to the forEach
method, as shown in Listing 1.
Listing 1. Java programming without closures
public interface Block<T> {
void invoke(T arg);
}
public class Utils {
public static <T> void forEach(Iterable<T> seq, Block<T> fct) {
for (T elm : seq)
fct.invoke(elm);
}
}
public class Test {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1,2,3);
Block<Integer> print = new Block<Integer>() {
public void invoke(Integer arg) {
System.out.println(arg);
}
};
Utils.forEach(nums,print);
}
}
The example is admittedly contrived and extremely simple, but consider it: how often in Java do you find yourself implementing an interface and passing the implementation to a method for execution? We can think of three immediate examples:
Runnable
andCallable
, which we pass to threads or thread pools for asynchronous execution.- Callback interfaces such as
ActionListener
, which we register for future execution in case a certain event occurs. Comparator
, which we pass to aTreeMap
for maintaining its sorting order.
In all these cases we use an interface, providing some functionality as an implementation of the interface. We then pass the functionality to a method for immediate or delayed, synchronous or asynchronous execution. Closures would simplify this process by allowing a more concise syntax, thereby eliminating some of Java’s verbosity. Beyond allowing more concise and readable Java source code, closures would add some functionality completely new to Java, such as custom control structures, which we explain later in the article.
Closures vs inner classes
In a recent blog post, James Gosling (aka Mr. Java himself) discussed the history of closures in Java:
Closures were left out of Java initially more because of time pressures than anything else. In the early days of Java the lack of closures was pretty painful, and so inner classes were born: an uncomfortable compromise that attempted to avoid a number of hard issues. But as is normal in so many design issues, the simplifications didn’t really solve any problems, they just moved them.
Gosling precisely describes our present situation: for eleven years, since the release of JDK 1.1, we’ve been using inner classes in place of closures. While they have served us well (you might recall how difficult and frustrating it was to implement callback interfaces without them) inner classes have never truly replaced closures. They simply are less powerful and more verbose than they need to be.
So, one thing all of the closures proposals agree to is the need to conceptually replace inner classes with a more powerful programming construct. Adding closures to the Java syntax would not mean losing inner classes; rather, the two constructs would be compatible and interchangeable. The advantage of closures, of course, is that they add flexibility and power not found in inner classes.
In the next section we’ll look at the specifics of how each proposal would bring closures to Java 7.
Closures: Three proposals compared
While the three closures proposals agree in their desire to bring the expressive power of closures to the Java syntax, they disagree about the manner of doing it. For one thing, the proposals differ — sometimes greatly — in how much additional power they would bring to the Java language. They also differ in terms of how closures are to be integrated into the existing language. One of the chief arguments against adding closures to the language is, of course, complexity. We’ll look at how each of the proposals addresses this issue below, following a brief overview of each one’s origin and basic intent.
Counting by numbers |
---|
To get a feeling for the attention this topic attracts, consider the following figures: with three proposals for closures in Java(not counting what some call the fourth proposal: no closures at all) Alex Miller’s Closures in Java 7 Web page lists nearly 150 articles, blog posts, or other resources related to this topic. No other feature in Miller’s coverage of proposed additions to Java 7 has received so much attention; most features have 10 entries at best. Even the runner-up, the fairly controversial Java Module System, has just 60 entries to date. |
BGGA
Issued in August 2006 the BGGA proposal started the “closures in Java” discussion. The acronym BGGA comes from the first letters of the last names of its four authors: Gilad Bracha, Neal Gafter, James Gosling, and Peter von der Ahé. Of that group, Neal Gafter has been the most vocal advocate for BGGA, which is undeniably the most ambitious of the three proposals. BGGA adds a lot of power to the Java language, but also a lot of complexity.
CICE plus ARM
CICE stands for “Concise Instance Creation Expression.” Developed by Bob Lee, Doug Lea, and Joshua Bloch, CICE has been strongly championed by Bloch. The CICE proposal is considerably less complex than BGGA and advocates an approach that is best described by its tagline: closures without complexity. In CICE, closures are essentially an alternative syntax for inner classes. CICE closures stick close to the existing Java language and do not add much new functionality.
One use case has especially shown the limits of CICE, and that is “resource management with finally
,” where BGGA outperforms CICE with its functional power. To compensate for this shortcoming Joshua Bloch has proposed an object-oriented resource management approach (an addition to the existing, more functional approach with finally
). He calls this proposal ARM (Automatic Resource Management). When most people talk about CICE today, ARM is implicitly included. Mark Mahieu has developed a prototype implementation for CICE plus ARM.
FCM plus JCA
FCM, which stands for First Class Methods is the closures proposal developed by Stephen Colebourne and Stefan Schulz. With respect to power and complexity this approach is somewhere between CICE and BGGA, and is much closer to BGGA. It mainly differs from the other two proposals in how it introduces closures into the Java language: not as an isolated novel concept, but embedded into an approach that allows handling of types and references of methods as first-class elements in Java. In FCM, a closure is just a special kind of method: the inner method.
BGGA also outperforms FCM by allowing for the implementation of custom control abstractions, which are static helper methods that receive a closure as a parameter. A separate proposal for Java control abstractions (JCA) addresses the need for custom control abstractions in FCM.
Next, we consider the specific benefits of closures and see how they’re handled by the three proposals.
The closures proposals in practice
One common goal of all the closures proposals is to simplify the process of passing a piece of functionality to a method. Let us see how the various proposals would achieve this goal.
CICE (Concise Instance Creation Expression)
CICE only introduces minor changes to the way that we currently pass functionality to methods in Java programs. We still need the Block
interface, which we use as the type of the functionality when we declare the forEach
method. Hence, the forEach
method does not change at all. The invocation syntax is more concise and convenient, however, as shown in Listing 2.
Listing 2. Declaration and invocation of method forEach using CICE
public interface Block<T> {
void invoke(T arg);
}
public class Utils {
public static <T> void forEach(Iterable<T> seq, Block<T> fct) {
for (T elm : seq)
fct.invoke(elm);
}
}
public class Test {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1,2,3);
Block<Integer> print
= Block<Integer>(Integer arg) { System.out.println(arg); };
Utils.forEach(nums,print);
}
}
Instead of creating an anonymous class of type Block<Integer>
we create a closure. In CICE the closure is called a concise instance creation expression, hence the name of the proposal. Essentially, the proposal boils down to a more convenient syntax, because we can replace the syntax for creating an anonymous class with the more concise syntax of the closure. The closure syntax is available for all interfaces with exactly one method, such as Runnable
, Callable
, or ActionListener
. CICE meets the goal of simplifying the use of these interfaces.
BGGA
This proposal introduces a new kind of type so far unknown in Java, namely a function type. A function type denotes the type of a closure. With the function type, we no longer need the Block
interface in our example. Instead we use the function type {T => void}
, which denotes a function with an argument of type T
that returns void
.
We use this function type when we declare the forEach
method’s second argument, as shown in Listing 3.
Listing 3. Declaration of method forEach with BGGA’s function type
class Utils {
public static <T> void forEach(Iterable<T> seq, {T => void} fct) {
for (T elm : seq)
fct.invoke(elm);
}
}
All closures implicitly have an invoke
method so that we need not change anything else in the forEach
method. Basically, you can assume that the compiler translates the function type to a synthetic interface type that looks like our Block
interface.
We use another quite similar function type, {Integer => void}
, when we create the actual closure that we pass to the call of the forEach
method, as shown in Listing 4.
Listing 4. Invoking forEach using a BGGA closure
class Test {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1,2,3);
{Integer => void } print
= { Integer arg => System.out.println(arg); };
Utils.forEaxh(nums,print);
}
}
The variable print
is a function reference of a function type and refers to a closure. It is initialized with a closure that in our example takes an Integer
and prints it. The closure is then passed to the forEach
method and applied to each element in the sequence.
FCM
The First Class Methods proposal goes one step further and does not only add function types (here called method types) that denote the type of a closure, but the type of a method in general. Closures in this proposal are just a special case of a method, namely an anonymous inner method, which is method without a name. Naturally, the syntax is different; our method type looks like #(void(T))
in this proposal and the closure is denoted as #(Integer arg) { System.out.println(arg); }
:
Listing 5. Declaration and invocation of method forEach using FCM
class Utils {
public static <T> void forEach(Iterable<T> seq, #(void(T)) fct) {
for (T elm : seq)
fct.invoke(elm);
}
}
class Test {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1,2,3);
#(void(Integer)) print
= #(Integer arg) { System.out.println(arg); };
Utils.forEach(nums,print);
}
}
As you can tell from the examples, the proposals use different syntax to achieve their goal, in this case passing functionality to a method, but the underlying idea is similar. Next we’ll look at how each proposal approaches closure conversion and type compatibility.
Closure conversion
All three proposals allow a certain amount of type compatibility among closures and interfaces types: a closure can be assigned to a variable of a compatible interface type. This is an important feature because it allows use of closures in all places where inner classes are currently used in the Java language. This type compatibility ensures that closures are backward compatible to interfaces and inner classes.
The idea backing this type compatibility is the observation that anonymous inner classes are typically used in situations where an implementation of an interface with just one method is needed. Common examples are callback interfaces such as ActionListener
with its actionPerformed
method or Runnable
with its run
method.
For the purpose of closure conversion, an interface type is considered compatible to a closure if it has a single method with a compatible return type and compatible argument types. (Actually this is a slight oversimplification: we are ignoring closures that throw exceptions, in which case the throws
clauses must also be compatible.) The compatible interface may have additional methods. As long as the additional methods are inherited from class Object
the interface is still considered an interface with a single method. The Comparator
interface is an example; it specifies a compare
method and an equals
method. Because every class inherits a default implementation of equals
from Object
, the Comparator
interface is treated like an interface with a single compare
method regarding compatibility to closures.
An example of closure conversion
Consider an example of closure conversion using the Runnable
interface, where we assign a closure to a regular reference variable of the interface type Runnable
. Currently in the Java language we would define an anonymous inner class in order to provide an on-the-fly implementation of Runnable
:
Listing 6. Old-style notation using an anonymous inner class
Runnable r = new Runnable() { public void run() { System.out.println("Hello World."); } };
new Thread(r).start();
In CICE, we basically do the same, but with a more concise syntax. For this reason, it is not surprising that a CICE closure is compatible with an interface variable.
Listing 7. CICE notation
Runnable r = Runnable() { System.out.println("Hello World."); };
new Thread(r).start();
In BGGA and FCM, the compatibility between a closure and an interface variable is not obvious and requires the implicit closure conversion.
Listing 8. BGGA notation
Runnable r = { => System.out.println("Hello World."); };
new Thread(r).start();
Listing 9. FCM notation
Runnable r = # { System.out.println("Hello World."); };
new Thread(r).start();
As you can see, all three proposals permit a substantially more compact notation than old-style Java and the concise notation is considered one of the key reasons for adding closures to the language. In fact, all three allow an even more convenient notation where the closure is defined in-place. This would allow us to eliminate the reference variable entirely and pass the closure literal in lieu of a Runnable
variable to the thread constructor, as shown here in BGGA notation:
new Thread({ => System.out.println("Hello World."); }).start();
This is the concise and convenient notation that all three closure proposals strive for and achieve using slightly different rules of syntax.
Non-local control statements
Naturally, the simple examples above only scratch the surface of what closures are about. Covering all of the issues related to each proposal is beyond the scope of this article. Moreover, in most aspects the proposals are relatively similar in what they propose — but there is one area where the proposals differ drastically.
In the BGGA proposal it is permissible for a closure to contain non-local control statements that affect the control flow of the context in which the closure is defined, not only the control flow within the closure itself. Listing 10 shows an example of a non-local return
statement. We use our earlier example, namely the forEach
method that applies a closure’s functionality to all elements in a sequence. The closure prints the argument it receives and contains a (non-local) return
statement that terminates the main
method as soon as the argument equals 3.
Listing 10. A non-local return statement in action
class Utils {
public static <T> void for<each(Iterable<T> seq, {T => void } fct) {
for (T elm : seq)
fct.invoke(elm);
}
}
class Test {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(1,2,3,4,5);
{Integer => void } print = { Integer arg ==> if (arg == 3) return; System.out.println(arg); };
Utils.forEach(nums,print);
}
}
The return
statement in the closure does not only return from the closure, but also terminates the main
method where the closure was defined. The effect is that with this closure our sample program terminates as soon as a sequence element equal to 3 is encountered; that is, it would print 1 2
and then stop.
The introduction of non-local control statements distinguishes BGGA from the CICE and FCM proposals. In both CICE and FCM a return
statement simply means “return from the closure.” The effect of corresponding closures in CICE and FCM would be that the closure returns as soon as a sequence element equal to 3 was encountered, but the forEach
method as well as the main
method would keep going — so the program would print 1 2 4 5
.
BGGA requires non-local return
statements because the proposal aims to enable us to factor out common control structures by means of closures — something we’ll demonstrate further below. The idea is that a closure behaves like a block of code that relates to the scope in which it is defined. That is, the closure can both access variables of the enclosing scope and affect the control flow of the enclosing scope, for instance by saying: “return from the enclosing method.”
Lexical binding
Lexical binding is the principle behind features like the non-local return statement. BGGA closures apply lexical binding to the following:
- Variables from enclosing scopes
- The meaning of
this
- The meaning of
break
,continue
, andreturn
Lexical binding of variables in a closure means that the closure can access variables from the enclosing scope. That’s not a new idea in Java. Local and anonymous classes have a similar feature: they can access final
variables of the enclosing scope. In a closure it is similar; just the restriction that the variable must be final
goes away. Instead, you may qualify the variable with a @Shared
annotation (at least in the BGGA proposal; the other two proposals allow access without final
or any other qualification).
Lexical binding of the this
keyword is new in Java, however. In anonymous inner classes, any use of the keyword this
refers to the instance of the inner class, not to an instance of the enclosing class. The enclosing class’s this
is referred to using different syntax, namely EnclosingType.this
. CICE will stick to this tradition, BGGA and FCM will break with it. In BGGA and FCM, the keyword this
will be lexically bound and will automatically refer to an instance of the enclosing type in which the closure is defined.
The fundamental difference between the proposals comes with lexical binding of control statements. In BGGA, not only the return
statement but also the control statements break
and continue
are lexically bound. Only BGGA proposes this feature; CICE and FCM do not have it.
The BGGA proposal needs the lexical binding of control statements in order to ease the factoring out of common code. In contrast, the emphasis of the FCM proposal in not primarily on refactoring, but more on enabling a functional programming style where functions and functionality (in the form of closures) are well supported. As a result, the FCM proposal has lexical binding for variables and this
, but not for break
, continue
, and return
— and for a good reason: non-local return statements have their pitfalls, as we will see shortly.
Returning a value from a BGGA closure
You might wonder how the compiler distinguishes between a local and a non-local return
statement in a BGGA closure. The answer is that there is no local return
statement in BGGA. A return
statement always returns from the nearest enclosing method or constructor in which the closure is called. If a closure needs to return a value it does so without an explicit return
statement. The last expression in a closure’s body always serves as an implicit local return
statement. For illustration, here is a BGGA closure that returns a value:
Listing 11. Returning a value from a BGGA closure
{double => double} f = {double x =>
double res = Math.log(x);
System.out.println("log of "+x+" is "+res);
res // implicit local return statement
};
The lexical binding of the control statements break
, continue
, and return
adds quite a bit of complexity to the BGGA proposal. We won’t mention all of the complications, but just consider the non-local return
statement. What if in our example the closure is not executed in a function that is invoked from main
, but in a function that is executed in a different thread? In that situation “return from main
” does not make any sense, because the other thread’s call stack does not have a main
method.
The BGGA proposal addresses this situation by raising an unchecked exception at runtime. In addition, something must be done to catch this kind of problem at compile time. BGGA would add a marker interface or some kind of syntax distinguishing restricted from unrestricted closures, where restricted closures are those that are not allowed to be executed in a different thread. We won’t go into further details, but suffice it to say that the fundamental problem remains: lexical binding of control statements can be error prone.
Control abstractions with closures
We’ve mentioned that the BGGA proposal includes lexical binding because the feature is needed for a fine-grained factoring out of common functionality. In fact, closures in BGGA are supposed to enable user-defined control structures, which ideally should be as easy to use as language features. The code to be abstracted in a refactoring might contain a break
, continue
, or return
statement, and such control statements are not supposed to prevent refactoring. For this purpose, BGGA needs lexical binding of control statements.
In fact, non-local control statements enable interesting and powerful closures. Here is a prototypical example of a refactoring that BGGA aims to enable: the use of explicit locks such as java.util.concurrent.Lock
. Consider a thread-safe stack abstraction that holds integers. It needs synchronization for its push
and pop
method and uses explicit locks for it:
Listing 12. Explicit locks in Java
public class Stack {
private static final int SIZE = 256;
private int[] arr = new int[SIZE];
private int cnt = 0;
private Lock lock = new ReentrantLock();
public void push(int elm) {
lock.lock();
try {
arr[cnt++] = elm;
} finally {
lock.unlock();
}
}
public int pop() {
lock.lock();
try {
return arr[--cnt];
} finally {
lock.unlock();
}
}
}
Obviously, the control structure that acquires and releases the lock is repeated in both the push
and the pop
method and we might want to factor it out. For this purpose we define a control abstraction withLock
, which is a method that takes a closure that represents the critical region.
Listing 13. Definition of control abstraction withLock using BGGA
public class Utils {
public static <T> T withLock(Lock lock, { => T} block) {
lock.lock();
try {
return block.invoke();
} finally {
lock.unlock();
}
}
}
Using the withLock
method we can refactor the push
and the pop
method as follows:
Listing 14. Refactoring push and pop using withLock
public void push(int elm) {
Utils.withLock(lock, { =>
arr[cnt++] = elm;
});
}
public int pop() {
Utils.withLock(lock, { =>
return arr[--cnt];
});
}
Regarding readability the BGGA proposal goes even one step further and defines a special control invocation syntax that renders it even more readable. To make it perfect we add a static import
statement for the withLock
method and — voilá— the withLock
control abstraction looks as pretty as the Java-language-defined synchronized
keyword:
Listing 15. Control invocation syntax in BGGA
import static Utils.withLock;
public void pushY(int elm) {
withLock(lock) {
arr[cnt++] = elm;
}
}
public int popY() {
withLock(lock) {
return arr[--cnt];
}
}
Putting syntactic sugar aside (and getting back to the point of lexical binding and non-local return statements) it’s evident that we truly need the lexical binding of the return
statement here. The closure’s return
statement is supposed to return from the pop
method, not just from the closure.
Alternate proposals for control abstraction
The withLock
control abstraction is a striking example of where the BGGA proposal is headed: it is a key goal of BGGA to allow for reusable abstractions such as withLock
that can be used to refactor existing programs and simplify future Java code. Neither CICE nor FCM have such an ambitious goal; instead both strive to simplify specific pieces of the Java syntax.
This said, both CICE and FCM have come up with proposals that address control structures. The Java Control Abstractions proposal suggests an addition to FCM that enables control structure in a way that is similar to what BGGA proposes. The main difference is that JCA deliberately distinguishes between regular use of closures and control constructs that use closures. Writing a control abstraction method such as withLock
is more complex than writing a regular method with closures such as forEach
. This is because the control abstraction method must take into account how return
, continue
, and break
and exceptions are handled.
Interestingly, BGGA is heading in a similar direction. The latest ideas regarding restricted vs. unrestricted closures also introduce a distinction between closure in control abstraction methods and regular use of closures. Eventually, we might see the two proposals converge.
Meanwhile, Automatic Resource Management Blocks is an addition to CICE that takes an entirely different approach to control abstractions. The observation is that much of the need for control abstractions circles around try
–finally
constructs and that there is basically a need for automatic resource release. For this reason, the proposal suggests language support for automatic resource disposal at the end of a block and an interface that would be used to make a class eligible for this kind of automatic disposal.
In conclusion
From a technical viewpoint the three closure proposals along with their respective companion proposals cover similar ground and strive for two main goals:
- Simplify the syntax for implementing and using certain simple interfaces (with just one method), such as
Runnable
,ActionListener
, andComparator
. - Allow common control structures to be refactored into shared utilities by means of closures; that is, enable user-defined control structures that are as easy to use as language features.
All three proposals clearly address the first goal, each in a slightly different way. Strictly speaking, the second goal is met only by BGGA and FCM+JCA. The CICE proposal takes an entirely different approach that does not aim to support custom-control structures, but suggests embedding into the language better support for resource management. Here the goals simply diverge.
In summary: CICE+ARM suggests a simple, easy-to-use feature with minimal modifications of the language; FCM+JCA is more ambitious; and BGGA proposes to add considerably more expressive power and flexibility to the Java language. The flipside of BGGA is quite a bit of complexity and fairly extensive changes to the language.
The closures debate in essence
Given the intensity with which this topic is occasionally discussed, you might get the feeling that closures are a matter of life or death for Java or your Java career. This argument is used by both people who want closures in Java and those who oppose them — or who might be willing to settle for the comparably simplistic CICE proposal.
An interesting Java.net opinion poll has been collecting “votes” for the three closures proposals for some time. In the poll, CICE and “no closures” are listed as two separate options, although their supporters want essentially the same thing: to keep the Java language simple. Combined, the “no closures” and CICE options have roughly 42% of the vote, which is roughly equal to the share of BGGA. FCM has nearly 15% of the votes, and less than 1% of voters have voted for “something else.”
Those who want closures in Java argue that if Java rejects closures, programmers will turn to other languages that support them well. (Even worse: it could be a language from the Microsoft .NET family.) Those who object to closures in Java argue that their inclusion would complicate the language beyond normal usability: mainstream programmers will turn away from Java, so the argument goes, and move on to simpler programming languages. In essence, those against closures are afraid that Java will turn into a guru language used only by experts in niche areas.
The “too complicated” argument is often heard in combination with a reference to generics, which many people also believe are too complex for what they achieve. The sentiment is that the evolution of Java toward ever increasing complexity must stop. As Joshua Bloch put it, we have “used up our complexity budget on generics, and in particular, on wildcards.”
Basically, there are two major opposing camps: one in favor of simplicity of use and minimal modification of the language, and the other in favor of increased expressive power at the expense of additional complexity. Which position is preferable is in the eye of the beholder. If we may risk a gaze into our crystal ball we would predict that one side-effect of the heated discussion is that we will not see closures in Java 7. (At the time of this writing, there is not yet a votable JSR for Java SE 7.)
While it may seem to some that the closures debate has already drawn on for long enough, the intensity of the debate, and the seemingly even support for BGGA and CICE/no closures (according to one poll) suggest that the delay is not unreasonable. At the least it will give us all plenty of time for further discussions.
Klaus Kreft has 20+ year of experience in the software business and currently works as a software engineer and system architect at SEN (Siemens Enterprise Communications GmbH & Co. KG).
Angelika Langer works worldwide as a freelance instructor, coach, and author with an independent curriculum of C++ and Java courses. Her areas of expertise include advanced C++ and Java programming, concurrent programming, and performance issues. She is the author of the Java Generics FAQ, an online resource covering new language features in Java 5.0, a Java champion, and a regular speaker at Java conferences.
Together, Klaus and Angelika author the column “Effective Java” for the German magazine JavaMagazin.