views:

213

answers:

2

Java 7 will have closures ( finally ), and I wonder how the existing code using single method classes/interfaces ( like Runnable, Comparator, etc ) will be used now.

Would that code be replaced? Will be a conversion of some sort? An extra method using the closure will be added?

Does anyone knows how is this going to work/what the plans are?

For instance, to use the FileFilter today we do:

....
File [] files = directory.listFiles( new FileFilter() 
                      public boolean accept( File file ) {
                          return file.getName().endsWith(".java");
                       }
                   });

Does anyone knows how is this going to work on Java7?

Maybe overloading the method File.listFiles to receive a closure?

File [] files = directory.listFiles(#(File file){
                    return file.getName().endsWith(".java");
                 });
+8  A: 

These classes/interfaces are called SAM (Single Abstract Method) types, and conversion of lambdas to SAM types is a central part of the project lambda proposal for JDK7. In fact, the most recent iteration of the proposal removes function types and only allows lambdas as instances of SAM types. With the latest version of the syntax (which is not final), your example could be written like:

File[] files = directory.listFiles(#(file){file.getName().endsWith(".java")});

With listFiles(FileFilter) unchanged from what it is now.

You could also write

FileFilter javaFileFilter = {#(file){file.getName().endsWith(".java")};

You may also want to take a look at this State of the Lambda document which is the latest update to the proposal and explains things in more detail. Note also that the specifics are all subject to change, though it's pretty certain that a lambda expression/block will be usable as a SAM type like I've described.

ColinD
The `#x(y){ return z;}` is already pushed to JDK7, does this mean they're going to add these lambdas on top of what's in there currently or remove the `#` thing entirely? SAM conversion is nice though, it will allow huge parts of Java environment to be closure'd automatically.
Esko
I like `#int(int y){ return z;}` better than `{y->z}`
OscarRyz
The syntax is not final, so it could change again, even back to the `#` thing. I got the feeling lots of people didn't like that though. One thing nice in the new version of the proposal is type inference for the arguments to the lambda, i.e. `{y -> z}` rather than `{int y -> z}`.
ColinD
Also, lambdas can still be blocks rather than expressions so you can certainly write `{y -> return z;}`, it's just convenient to be able to exclude `return` and the `;` when you just need an expression (which is fairly common, I think).
ColinD
Actually, the proposal would require you to write `{y -> yield z;}` rather than using `return`, in the hopes of saving `return` for a "long return" (return from the method the lambda is scoped in, essentially). Seems like most people aren't in favor of using `yield` for that though.
ColinD
Isn't `yield` a whole different case than `return` in general? I can't imagine `collection.find({ -> yield it.value == x; });` feeling idiomatic at all.
Esko
Well, with a simple expression like that it would typically be idiomatic to just use the expression itself `collection.find({it -> it.value == x})`. I could be wrong, but I don't feel like `yield` is going to make the cut though.
ColinD
Updated to the current syntax, which is more like `#(args){...}` with the types of the args optional if they can be inferred.
ColinD
A: 

Existing code isn't affected and won't need replacing.

EJP