Skip navigation
ANNOUNCEMENT: community.oracle.com is currently Read only due to planned upgrade until 29-Sep-2020 9:30 AM Pacific Time. Any changes made during Read only mode will be lost and will need to be re-entered when the application is back read/write.

Today, a tantalizing announcement by Mark Reinhold about closures in Java 7 has made its way through the twittersphere.

http://s3.amazonaws.com/twitpic/photos/large/43627883.jpg?AWSAccessKeyId=0ZRYP5X5F6FSMBCCSE82&Expires=1258604506&Signature=10TTU0ilHSrHnms%2BxpUrlu%2Fbfi8%3D

On the same day, Neal Gafter updated his closure proposal (known as the BGGA proposal, named after the initials of Bracha, Gafter, Gosling, and von der Ahé, and not at all related to the B. G. G. A. organization).

Presumably the timing is not a coincidence.

The proposal is a bit technical, so I thought I'd translate my understanding of it into some use cases. Here goes.

  • Running something on a thread pool: 
    pool.submit(#() { for (int i = 1; i < 1000000; i++) doWork(i) });
    

    Here, the #() { ... } denotes a function literal.#() indicates that the function has no parameters. (I guess the return type is inferred.) The function body is a block, enclosed in braces.

    If you squint really hard, the # looks like a λ:-)

    The function object is automatically converted to aRunnable because the Runnable interface has a single method, also with no parameters.

  • Adding a button listener: 
    button.addActionListener(#(ActionEvent e) System.out.println("Hi!));
    

    This is pretty much the same as the previous example, except that you can have a single expression after the#(...), and then you don't use braces.

    It is certainly an improvement over

    button.addActionListener(
       new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
             System.out.println("Hi!"); } } );
    
  • Sorting with a comparator: 

    Here we sort a string list by increasing length:

    Collections.sort(strings, #(String a, String b) a.length() - b.length());
    

    which can also be written as

    Collections.sort(strings, #(String a, String b) { return a.length() - b.length(); });
    

    Note that you need a return and a ; if you use a block instead of an expression.

  • Using a java.util.concurrent lock: 
    withLock(myLock, #() {
       if (account2.getBalance() < amount) return; 
       account1.deposit(amount);
       account2.withdraw(amount);
    });
    

    Here we assume that some friendly soul has written awithLock method. You can find the code for that method in Neal's proposal. I am purposefully notreproducing that code because it will frighten small children. But so what—it's something that only library writers worry about.

    This is similar to my first example, except for the return statement. In prior versions of the BGGA proposal,return could return from the method containing thewithLock method. That was nifty in a way—it allowed new control statements that feel just like the built-in ones. But it was also potentially confusing. Nowreturn simply returns from the function, and execution continues with the statement following withLock.

  • Filtering a collection: 
    double amount = 1000;
    Collection<Account> result = filter(accounts, #(Account a) a.getBalance() < amount);
    

    Again, I assume that some friendly soul has written afilter method.

    Note that the closure can reference the amountvariable from the enclosing scope. It doesn't have to befinal because I am never assigning to it after I initialize it.

  • Updating a variable in the enclosing scope: 
    @Shared int clickCount = 0;
    button.addActionListener(#(ActionEvent e) { clickCount++; });
    

    The @Shared is required because theclickCount variable is mutated.

    By the way, this is another one of those things that is incredibly convoluted in Java without closures. int is a primitive type and Integer is immutable. The path of least resistance is

    final int[] clickCount = new int[1];
    button.addActionListener(
       new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
             clickCount[0]++; } } );
    

Overall, I like it. The simple things are simple, and there don't seem any hidden pitfalls.

Of course, someone out there will say "Oh my, oh my, that#(ActionEvent e){...} makes my head explode. It's not cuddly and comfortable like new ActionListener() { public void actionPerformed(ActionEvent e) {...}}”.

To which I'll say “I rest my case”.

More interestingly, someone on the Project Coin mailing list tried to muddy the waters by asking how this feature interacts with other new features of Java 7, like

try (Closeable c = #() { System.out.println("YOUR HEAD A SPLODE"); }) {
   // ...
}

Ok, that means that the close method ofc will be invoked in the finally clause, and that method is set to the #() {...}. What's so hard about that?

If this is indeed to come to pass in Java 7 (and I have absolutely no inside knowledge whether it will), I am willing to wait a bit longer. What do you think?