Library tutorials & articles
The Beauty of Closures
- Introduction
- Filter 1: Matching short strings (length fixed)
- Filter 2: Matching short strings (variable length)
- Comparing capture strategies: complexity vs power
- What's the big deal?
Comparing capture strategies: complexity vs power
Clearly the Java scheme is more restrictive, but it does make life significantly simpler, too. Local variables behave in the same way they've always done, and in many cases the code is easier to understand, too. For example, look at the following code, using the Java Runnable interface and the .NET Action delegate - both of which represent actions taking no parameters and returning no value. First let's see the C# code:
// In Example3a.cs
static void Main()
{
// First build a list of actions
List<Action> actions = new List<Action>();
for (int counter = 0; counter < 10; counter++)
{
actions.Add(() => Console.WriteLine(counter));
}
// Then execute them
foreach (Action action in actions)
{
action();
}
}
What's the output? Well, we've only actually declared a single counter variable - so that same counter variable is captured by all the Action instances. The result is the number 10 being printed on every line. To "fix" the code to make it display the output most people would expect (i.e. 0 to 9) we need to introduce an extra variable inside the loop:
// In Example3b.cs
static void Main()
{
// First build a list of actions
List<Action> actions = new List<Action>();
for (int counter = 0; counter < 10; counter++)
{
int copy = counter;
actions.Add(() => Console.WriteLine(copy));
}
// Then execute them
foreach (Action action in actions)
{
action();
}
}
Each time we go through the loop we're said to get a different instance of the copy variable - each Action captures a different variable. This makes perfect sense if you look at what the compiler's actually doing behind the scenes, but initially it flies in the face of the intuition of most developers (including me).
Java forbids the first version entirely - you can't capture the counter variable at all, because it's not final. To use a final variable, you end up with code like this, which is very similar to the C# code:
// In Example3a.java
public static void main(String[] args)
{
// First build a list of actions
List<Runnable> actions = new ArrayList<Runnable>();
for (int counter=0; counter < 10; counter++)
{
final int copy = counter;
actions.add(new Runnable()
{
public void run()
{
System.out.println(copy);
}
});
}
// Then execute them
for (Runnable action : actions)
{
action.run();
}
}
The meaning is reasonably clear with the "captured value" semantics. The resulting code is still less pleasant to look at than the C# due to the wordier syntax, but Java forces the correct code to be written as the only option. The downside is that when you want the behaviour of the original C# code (which is certainly the case on occasion) it's cumbersome to achieve in Java. (You can have a single-element array, and capture a reference to the array, then change the value of the element when you want to, but that's a nasty kludge).
Related articles
Related discussion
-
The Beauty of Closures
by markbuxbaum (1 replies)
-
Binary Studio | software development outsourcing Ukraine
by shane124 (4 replies)
-
Socket Programming in C# - Part 1
by lespero (24 replies)
-
A open source C#-Java conversion tool
by sindy55 (0 replies)
-
how to Convert Lambda Expression in C# to Vb.Net
by selvakumarig (1 replies)
Related podcasts
-
Stack Overflow: Podcast #29
This is the twenty-ninth episode of the StackOverflow podcast, wherein Joel and I discuss the following: The downside of being a PC gamer: it's prime game release season. My productivity last week was nil due to the release of Fallout 3, as I discuss on my blog. But it was totally ...
Events coming up
-
Nov
17
Portland Java User Group
Portland, United States
This month's topic: TBD----------PJUG meetings start with eat+meet+greet time (pizza and beverages are provided), followed by the featured speaker, then some time for Q&A, discussion, and sometimes a drawing to give away swag. :)It is...
Thanks Jon for a clear well-written article. I reached this article after downloading Ruby, and wanted to brush up on closures and some other supported language features. I appreciate the full code examples- many times authors leave out details, which can make the reader feel as if he or she is "missing something". Best Regards, Mark
!--removed tag-->