Here’s examples from my actual code of five lesser-known Java features, in increasing order of how much fun I had discovering they exist.
Anonymous classes
These are fairly well-known, so let’s go for a freaky example – an anonymous class declaration within the head of a (labeled!) for loop:
sentence : for (List children : node.getOrderedChildrenBySpan( sentence.getOrderedTerminals(), new Test() { @Override public boolean test(Node object) { return false; } })) { for (Node child : children) { String tag = child.getLabel().getTag(); if (tag.contains("-SBJ")) { break sentence; } tags.add(PTBUtil.pureTag(child)); } }
Enums
Boring, I know. I’m mentioning them here for completeness because I found out about them rather late and was like, hey, cool, that’s much nicer and cleaner than working with explicit integer constants.
public enum EditOperationType { DELETE, INSERT, SWAP, MATCH; @Override public String toString() { switch(this) { case DELETE: return "delete"; case INSERT: return "insert"; case SWAP: return "swap"; default: return "match"; } } }
Generic methods
Luckily, the following code is no longer live.
@SuppressWarnings("unchecked") public T retrieve( Class type, int id) { return (T) getStoreForType(type).retrieve(id); }}
Instance initializers
I know I discovered these once thinking I needed a constructor in an anonymous class and wondering how to do this, because how would one declare a constructor in a class without a name? It did not remain in my workspace, however, and I never used an instance initializer again. In the case of anonymous classes, I tend to use final variables outside of the anonymous class, or derive them from classes whose constructors already handle everything I need. So I’m pulling an example from someone else’s code:
_result = new ContainerBlock() { { setPanel(_panel); setLayout(LayoutFactory.getInstance() .getReentrancyLayout()); addChild(unboundVarLabel); } };
Multiple type bounds
public abstract class IncrementalComparator< T extends HasSize & HasID> { // ... }
I wonder what’s next.
Enums have a very nice use in being the de-facto best way to implement singletons in Java: http://stackoverflow.com/questions/427902/java-enum-singleton
Instance initializers are incredibly nice if you want to populate your Collection (which Java Syntax doesn’t otherwise allow for.)
Something like final Collection f = new LinkedList() {{ add(foo1); add(foo2); addAll(fooList); }};
This is especially interesting if you also want to override the parent’s methods and also use some of the instance methods at construction time.
Java Generics are totally awful, and Angelika Langer’s 500+page FAQ is proof of that. There’s some pretty esoteric stuff in there, that abuses how the compiler stutters together its flimsy reasoning about them.
Can you give an example?
Thought so.
Seriously, though Java Generics are a bitch to learn, after all these years I find there’s little to be said against the way they were done.
Hey, not so fast!
Well, yeah, half a year is probably enough time to expect me to answer. But the answer isn’t easy. The problem with generics isn’t that they’re terribad, and it’s easy to see why, but because of their idiosyncrasies and edge cases. It takes a bit longer to explain that, so I started a post over at my own blog (sorry, no way to put this much text in a comment. Well, there’d be a way, but you wouldn’t want to read it.)
I have more to say on the topic, actually. But it’ll have to wait, since just writing this much took me some week and a half.
See here: http://a-dimit.blogspot.com/2011/11/re-highbrow-java-or-java-generics-and.html