Monday, December 12, 2005

Tiger Beat!

1. Enhanced for loop is pure coding joy, especially in nested loops, but you will be suprised at how often you can't use it: you need the index, special exit condition (I'm not a "break" man), or you have an iterator.

2. Generics will improve your API dramatically. The rap on them is that creating your own generic classes can get messy, and that's true. But it's not _that_ bad, and 99% of the time you are simply using generic classes, which is completely simple.

Before generics, we often deliberated about what type to return when a method produced a group of objects (Not a group of "expensive" objects, like objects read from a database - they pretty much necessitate an Iterator). Arrays were succinct and type-safe. Collections were what the method often used internally and were more flexible, but lacked type safety. For us, in a big system, readability won out, and we chose arrays. Overall, I was happy with the choice, but it didn't sit well how often we'd convert a List to an array at the end of the method. Generics resolved this completely. Now all methods return "generified" collections objects, and we get the best of both worlds.

Map.get/containsKey/remove and Set.contains are NOT generic. Good discussion:
http://forum.java.sun.com/thread.jspa?threadID=465357&messageID=2139377

It takes a while to really get used to the fact that generics info is not available at runtime. Once you understand that, you'll find yourself more a user of generics classes than an author of generics classes.

3. java.util.concurrent - Great libraries change how you think about problems. java.util.concurrent is no exception. Simple concurrency problems are now actually simple to solve. I'm able to express amazingly powerful concurrent problems in simple and safe code. I don't know how I lived before ConcurrentHashMap, Executor, Callable, and Future. I now look forward, rather than dread, the next concurrency programming problem.

4. @Override - Love it. Even though I haven't programmed Perl in 8 years, I still get a thrill when the compiler points out a problem I never would have noticed. Errors that @Override solve are pretty rare, but they've saved me once, and that's enough for the "Love it" designation. While I understand it would be trickier, an @Implements would be cool to. @SuppressWarning allows to turn certain compiler warnings on which I avoided in the past, because I didn't want warnings for the handful of "special cases" of a warning.

5. String.contains - Can you believe it? I feel like a Programmer of the Future every time I use this baby.

6. OutOfMemory actually TELLS you what kind of memory we ran out of! Before 1.5, you had to figure out what kind: heap? perm heap? thread stack? They were clearly emboldened by the rejoicing of this fix, and tackled an even MORE amazing problem in Mustang: ClassCastException will tell you what was casted!

7. Thread.getStackTrace/getAllStackTraces. If you run into race condition/locking problems, and don't have the luxury of reproducing in your IDE, a JSP that displays Thread.getAllStackTraces is pretty useful.

8. enums - Typesafe enums are essential for clarity in big APIs, and I hope they get more attention now that they're first class in Java. If you are leary of Generics introducing clutter to API, you won't like this:
public abstract class Enum>
I tried writing a utility method for enums, and it actually set my brain on fire.

Eclipse has a neat compiler option - to warn/error if a switch statement doesn't cover every member of the enum. This is a wonderful tool, as you often want to take an action based on the value of an enum, and it's imperative to cover every possible value of the enum. However, I haven't used switches or breaks since I was a C programmer. I was torn between the joy of a new compiler warning, and the mess that is "switch". I tried and tried, and eventually just had to drop the switch. Its freaky scoping and flow was just too much to swallow.

9. Monitoring - Anybody who's had problems in production will love JConsole and java.lang.management.ManagementFactory. You'll also love System.nanoTime if you've ever tried timing operations with System.currentTimeMills. currentTimeMillis could not measure down to the millisecond, so any "fast" operation would result in times of 0, 16 or 32 milliseconds. Not a problem with nanos!

I'm sure I'm forgetting quite a bit, but in short, I'm in love. Tiger represents a good balance between Sun's traditional conservatism and the pressure they face from their emerging competition. I hope they maintain their discipline as well as their fear.

No comments: