let's play TDD, tackles closures in java

Brian Goetz brian.goetz at oracle.com
Mon Dec 20 02:49:46 PST 2010


On Dec 15, 2010, at 1:55 PM, Llewellyn Falco wrote:
>> Yes, those 8 lines of code do seem easy compared to
> 
> boolean fired = false;
> model.addTableModelListener(#{e -> fired = true});
> model.doThing();
> assertTrue(fired);

So, in what thread is the closure going to get executed?  Listeners are generally fired in the EDT (in correctly written programs).  Which means that this code example has a data race, and is therefore broken.  

This is *exactly* why the stricture against mutating locals from closures is in place!  

> boolean fired[] = {false};

> model.addTableModelListener(#{e -> fired[0] = true});
> model.doThing();
> assertTrue(fired[0]);

And again, data race!  The blade guards were there for your protection, you removed them with that "hey, I know what I'm doing" attitude, and proceeded to cut your fingers off.  Nicely done. 

> the point is, once again we have are going to have an industry standard
> recommendation to write the following code:

Who is making these "industry standard recommendations"?  I don't know anyone who thinks the "one-element-array" hack is a good idea.  If this is what people are recommending to you, perhaps you should take your recommendations from someone else....

Instead, how about:

final AtomicBoolean b = new AtomicBoolean();
model.addTableModelListener(#{ e -> b.set(true) });
model.doThing();
assertTrue(b.get());

This is a perfectly safe way to do what you want, and it is not even any longer (vertically) than the version you want (with the mutable local boolean.)  




More information about the lambda-dev mailing list