Thoughts on Java 5 features
Prompted by the recent Java Posse podcast (episode 79) where they briefly talked about people's experiences with the features that were introduced into Java 5, here are my thoughts on the features I use the most.
- For each loop : Without a doubt, this is my favourite Java 5 feature. In the majority of cases where you simply want to iterate over a collection of like objects, this is a real time saver because you no longer need to write that boilerplate iterator code. Like many others, I often have to revert back to the old way of doing things, but only if I really have to.
- Generics : Generics go nicely hand-in-hand with the for each loop, providing you with a way to iterate over objects of a specific type. I like generics a lot and they've really cleaned up the codebase, making it much more explicit and less prone to runtime ClassCastExceptions and the like. On the downside, the syntax is a little verbose. Of course, you don't have to specify the type within angle brackets everywhere, but tools like Eclipse and IDEA start warning you about unsafe conversions if you don't. The other problem that I've encountered a number of times is that it's easy to get tripped up by type conversions and casting now that you have two class types (the containing class and the type) to deal with. That's just part of the learning curve though.
- Autoboxing : From my experience, autoboxing is both a blessing and a curse. On the positive side, it's another great timesaver and it's really nice to not have to think about conversion between primitives and objects. On the negative, auto-unboxing has caused me a fair amount of grief because of code like this.
Integer int = null;
// do some stuff
SomeObject object = new SomeObject();
object.aMethodThatTakesAPrimitive(int);
Bang, NullPointerException for no apparent reason. Nasty, really nasty. Geert Bevin blogged about this 2 years ago, yet it's still tripping us up. On a related note, prior to autoboxing I'd not come across APIs that used the boxed primitives in their interfaces. Now, I'm starting to see this more, which is quite neat because it's easy to represent null values with null rather than a magic number (e.g. -1). On the other hand, you get nasty NullPointerExceptions when you're least expecting them and you still have to put effort into mapping nulls to some magic value where subsequently called APIs use primitives. - Concurrency : This is a real gem, with components like the ExecutorService proving to be real timesavers when it comes to build thread pools, etc. If you're thinking of building your own thread pool implementation, take a look at this first!
Lots of organisations and projects that I've seen recently are still using Java 1.4.2 and below, but fortunately my current project is running Java 5 so I'm gradually getting around to using most of the "new" features. With Java 6 just around the corner and Java 5 over 2 years old, it's nice to be using Java 5 commercially at last. Oh well, who wants to live on the bleeding edge anyway? ;-)
Re: Thoughts on Java 5 features
I'd still recommend using an actual object to represent 'nothing'. You can have a wrapper object that can either be 'nothing', or 'something'.
I stole the Maybe type from Haskell (I hope they don't want it back), which quite nicely lets me never have to use null again:
http://functionalpeas.googlecode.com/svn/trunk/src/fpeas/maybe/
Autoboxing isn't transitive
Autoboxing isn't transitive
With formatting like that, it's not surprising that you didn't get it :-)
The problem is that when you have == between an int and an Integer, it auto-boxes the int and does object equality (with .equals())
However, if the two objects are already integer objects then == does object identity, which returns false.
So comparison only works between int and int, int and Integer, Integer and int, but not integer and Integer. And if you don't know whether it's an autoboxed int or not, you don't know what will happen.
Autoboxing isn't transitive
Autoboxing isn't transitive
There's no concept of 'autoboxing' being transitive or not. A transitive function is one such that if a*b and b*c, then a*c also holds. Equality is defined as a transitive function. The fact that autoboxing confuses (neededlessly) int and Integer types means that it breaks the transitivity of the == operation. Therefore, autoboxing is unsound because it violates a sound mathematical definition; namely, that == must be transitive.
Simon is a hands-on software architect and a senior consultant at 

