Search |
||
Announcement - "No Closures" prototypePosted by brucechapman on March 8, 2008 at 1:39 AM PST
All the major closures proposals now have prototype implementations available. But until we can play with the final option "No Closures" we're not in the best position to make a good decision. So it is with pleasure that I announce the availability of a prototype for "No Closures". With this jar file and JDK 6, you can effectively cast a method to a SAM type. For those not following the various closures proposals too closely, a SAM type is a "Single Abstract Method" type. That is, a class or an interface with only one method that is abstract.
So to cast a method to a SAM type, the method should have the same argument types and return type as the SAM, but it can have any name. It may NOT be private. You then annotate that method with Here is a method declared to be castable as a Runnable
In order to cast that method to a Runnable, you do this
Thats right, you get the Runnable by calling a static method on the Runnables class, and pass the object that owns the method.new Thread(Runnables.slowStuff(this)).start(); So how does this work?
In the jar file containing the annotation there is also an annotation processor. For each SAM type with at least one corresponding Those generated static methods look like this If you want to pass additional arguments to the method which are not part of the SAM, just annotate those with @As.Additional, and when you call the generated class, pass those arguments. ExampleHere is a small swing app that demonstrates things.
This should compile with JDK 6. You will find the generated Runnables and ActionListeners classes whereever it is you tell javac to place generated classes (the -s option if used, otherwise in the same place as the compiled .class files). What's Hot and What's NotThis is designed to be work correctly even if you do incremental compiles. The processor remembers all the SAMs for the project and keeps them up to date, even if you only compile classes one by one.
Currently this doesn't work for generic SAM types. That means you can't use it to cast a method I don't think this is as good as any of the closures proposals, except in one respect, you don't have to wait for JDK 7 to use it. »
Related Topics >>
Programming Comments
Comments are listed in date ascending order (oldest first)
Submitted by fabriziogiudici on Sat, 2008-03-08 02:58.
As a minor remark, probably just appending the 's' for the generated class is too risky to clash with an existing class name. What about generating a RunnableSAM instead? It's less sexy, but also less risky to clash.
The generated class is in the same package as the annotated method, so the naming clash is the responsibility of the user. I thinks it's easily avoided. - Bruce
Submitted by zero on Sat, 2008-03-08 03:42.
really cool,
let's hope the news spread!
looking forward for the next feature release :-)
Submitted by stefan_schulz on Sat, 2008-03-08 06:50.
I like this idea. It's actually a somewhat pimped method reference solution rather than closures. The nice part is the additional parameter approach, which makes any variable to be used within the method (i.e. where a closure would close over) an explicit parameter and still make the method match the SAM.
Submitted by brokenshard on Tue, 2008-03-11 23:02.
I agree with fabriziogiudici, just the extra 's' may cause some problems...
Submitted by mcnepp on Mon, 2008-03-10 09:03.
Hi Bruce,
I like this idea, and it works like a charm. It's a pity you didn't publish the source code - it would make a good tutorial on writing annotation processors! The source code is coming, I just jumped the gun while the topic was hot - Bruce I don't really see why @As.Additional is necessary, though. Appending additional parameters to the generated helper method should be the default behaviour without the need to annotate them with @As.Additional. Yes you could do it that way. I made them explicit because it makes it easier to check that the method matches the SAM, and being explicit means the documentation is simpler. A previous incarnation of this concept worked for multiple method interfaces, and once you understood how to do it, it was quite nice, but I just couldn't make the documentation simple. So I dropped the feature. - Bruce
Submitted by opinali on Mon, 2008-03-10 09:26.
It's so wonderful that after sixty years of evolution in programming languages, we can finally use C-like function pointers in Java... hooray!! Please gimme longjmp() too, in the next release. </sarcasm>
Isn't that what throw new RuntimeException() does? - Bruce :)
Submitted by aberrant on Mon, 2008-03-10 10:25.
From looking at your implementation it seems that one cannot use the @As with private methods. Have I missed something?
You missed the fact that the method is called from an inner class which is defined in the generated class in the same package. Thats why it doesn't need to be public, but cannot be private. - Bruce
Submitted by rdjackson on Wed, 2008-05-21 19:45.
Any updates on when you will get around to releasing the code for this? I'm still very interested in taking a look at it.
Submitted by rdjackson on Wed, 2008-03-19 20:30.
When I first saw this I really liked the idea a lot. Now that I've had time to digest it I like it even more. Like others have stated I'm really looking forward to seeing the source for this. On a side note when using the supplied jar under Netbeans 6.1 the generated java file gets put in the build directory verses the source directory so the IDE will not build the application correctly. If I manually move the generated java file all is fine. Also the combination of this and JSR-296 will really rock.
The Netbeans Wiki has information on how to set up a project to work with an annotation processor. Its not too hard, but it would be nice if it was a no brainer. I have filed a tree of bugs to have that and related issues addressed. - Bruce
Submitted by rdjackson on Thu, 2008-03-20 19:37.
Thanks for the link to the Netbeans wiki on how to get this setup so that things just work. I can't over express How much I really like this Idea and solution to the "No Closures" needed approach.
Submitted by hlovatt on Mon, 2008-03-17 21:41.
This is an excellent suggestion. Much simpler than any of the proposals - including my own ( http://www.artima.com/weblogs/viewpost.jsp?thread=182412 ). I look forward to seeing the source.
Presumably an @Shared annotation could be added to allow write access to a local variable.
NO I can't see a way to implement @Shared. That would involve accessing a local variable in another method, or passing the variable by reference. You can't do that in Java 6 as far as I know, at least not without some gnarly bytecode manipulation. Also many of the useful use cases involve situations where the @As method is executed later and the code that "cast" the method to a SAM is no longer on the stack. However because the @As method is normally in the same class as the method that casts it, it can access fields. Alternatively you could achieve the same effect as @Shared by using the @As.Additional mechanism to pass a Future to the method. -Bruce
|
||
|
|