Archive for the ‘Java’ Category

The dark side of {{ }}

Saturday, December 22nd, 2007

Despite having typed in an enormous amount of Java code over the past seven or eight years, my “discovery” of


return new Foo() {{
  setThingy(whatever);
}};

was embarrassingly recent. Because it lets me work more with values than with statements, I like it a lot, and I try to think in terms of using it.

For those still unaware of this surprisingly old feature of the language, it’s possible in general to add anonymous blocks to class definitions. Everybody knows about


static { foo = new BigFoo(); }

Without the static keyword, the block is treated as an appendage to the constructor code. (I guess they run in declaration order, but I don’t care about that at the moment.) Thus the notation

new T() {{ code; }}

means to construct an anonymous subclass of T with some random code that runs along with the no-args constructor for T. (Of course you can also do that when the constructor does have arguments.)

The dark side of that trick is probably obvious to everybody except me, because the dark side has crept in and wasted a lot of my time recently. The code that you type into that {{ }} block is of course code that’s treated as being in the lexical context of the subclass, not that of your surrounding code. Durr. If the initialization statements refer to method names or variable names that are visible in the base class, then the statements are interpreted as being in those terms. That’s really nice when you’re using this to populate a HashMap


return new HashMap() {{
  for (DungHeap dh : allHeaps()) put(dh.getName(), dh);
}};

However, if the base class you’re subclassing has some protected member variables, watch out! The final variables in the surrounding code you’re referencing as part of the initialization will be shadowed. Same goes for utility methods you’d like to call.

This got me just today with a context variable called “headers”. I was initializing a new MimeMessage instance. Guess what’s a protected member variable of a MimeMessage instance?

I still like that notation, for now at least.