It looks like anonymous class provi开发者_JAVA技巧des the basic functionality of closure, is that true?
There is almost no difference. In fact the there is an old saying about closures and objects. Closures are the poor man's object, and objects are the poor man's closure. Both are equally powerful in terms of what they can do. We are only arguing over expressiveness.
In Java we are modeling closures with Anonymous Objects. In fact a little history here is that originally Java had the ability to modify the outward scope without the use of final. This works and worked fine for Objects allocated in the local method scope, but when it comes to primitives this caused lots of controversy. Primitives are allocated on the stack so in order for them to live past the execution of the outer method Java would have to allocate memory on the heap and move those members into the heap. At that time people were very new to garbage collection and they didn't trust it so the claim was Java shouldn't allocate memory without explicit instruction from the programmer. In efforts to strike a compromise Java decided to use the final keyword.
http://madbean.com/2003/mb2003-49/
Now the interesting thing is that Java could remove that restriction and make use of the final keyword optional now that everyone is more comfortable with the garbage collector and it could be completely compatible from a language perspective. Although the work around for this issue is simple to define instance variables on your Anonymous Object and you can modify those as much as you wish. In fact that could be an easy way to implement closure style references to local scope by adding public instance variables to the anonymous class through the compiler, and rewriting the source code to use those instead of stack variables.
public Object someFunction() {
int someValue = 0;
SomeAnonymousClass implementation = new SomeAnonymousClass() {
public boolean callback() {
someValue++;
}
}
implementation.callback();
return someValue;
}
Would be rewritten to:
public Object someFunction() {
SomeAnonymousClass implementation = new SomeAnonymousClass() {
public int someValue = 0;
public boolean callback() {
someValue++;
}
}
implementation.callback();
// all references to someValue could be rewritten to
// use this instance variable instead.
return implementation.someValue;
}
I think the reason people complain about Anonymous inner classes has more to do with static typing vs dynamic typing. In Java we have to define an agreed upon interface for the implementor of the anonymous class and the code accepting the anonymous class. We have to do that so we can type check everything at compile time. If we had 1st class functions then Java would need to define a syntax for declaring a method's parameters and return types as a data type to remain a statically typed language for type safety. This would almost be as complex as defining an interface. (An interface can define multiple methods, a syntax for declaring 1st class methods would only be for one method). You could think of this as a short form interface syntax. Under the hood the compiler could translate the short form notation to an interface at compile time.
There are a lot of things that could be done to Java to improve the Anonymous Class experience without ditching the language or major surgery.
As far as they both affect otherwise "private" scoping, in a very limited sense, yes. however, there are so many differences that the answer might as well be no.
Since Java lacks the ability to handle blocks of code as true R-values, inner classes cannot pass blocks of code as is typically done in continuations. Therefore the closure as a continuation technique is completely missing.
While the lifetime of a class to be garbage collected is extended by people holding inner classes (similar to closures keeping variables alive while being rebound to the closure), the ability of Java to do renaming via binding is limited to comply with the existing Java syntax.
And to allow threads to properly not stomp over each other's data using Java's thread contention model, inner classes are further restricted with access to data that is guaranteed not to upset, aka final locals.
This completely ignores the other inner classes (aka static inner classes) which is slightly different in feel. In other words, it touches upon a few items that closures could handle, but falls short of the minimum requirements that most people would consider necessary to be called a closure.
IMHO, They serve a similar purpose, however a closure is intended to be more concise and potentially provide more functionality.
Say you want to use a local variable using an anonymous class.
final int[] i = { 0 };
final double[] d = { 0.0 };
Runnable run = new Runnable() {
public void run() {
d[0] = i[0] * 1.5;
}
};
executor.submit(run);
Closures avoid the need for most of the boiler plate coding by allowing you write just what is intended.
int i = 0;
double d = 0.0;
Runnable run = { => d = i * 1.5; };
executor.submit(run);
or even
executor.submit({ => d = i * 1.5; });
or if closures support code blocks.
executor.submit() {
d = i * 1.5;
}
精彩评论