Why I'm Not a Fan Of Java's Auto-Unboxing
Join the DZone community and get the full member experience.
Join For FreeStarting with Java 1.5, the Java compiler started automatically taking care of converting boxed versions of primitive types into primitive types where necessary, and vice-versa. While I’m generally in favor of anything that makes programming languages easier to use, provided it doesn’t overly-complicate things, I’ve never been a huge fan of the way it was done.
Most languages either have C or C++ style primitives or object-style numbers and booleans, but Java has always had an odd mix of the two. The easiest thing for a programmer is to simply go all the way to the object model and be done with it; my assumption is that Java didn’t do that both for the sake of continuity with C and for the sake of raw performance.
But unfortunately, the solution of auto-converting between the two worlds doesn’t really solve the problem that there are differences there that you have to be aware of. The main difference is around null; a primitive type can’t be null, and a boxed type can, so every time you unbox an object you have to worry about how to handle null values. If you do the unboxing by hand, at least you might have to think about it, and if you don’t at least it’ll be obvious what the error is. But the auto-unboxing both manages to not handle null for you and manages to completely hide the errors when they do happen, which is basically a huge lose-lose in my book. I managed to spend far too long the other day trying to figure out why the following line of code was throwing an NPE:
modifier.setEligible(!pattern.getDisplayEligibility());
My instinct is that an NPE is caused by a method call or field reference on a null object, so clearly either “modifier” or “pattern” has to be null here, right? So after staring hard at the code for several minutes to try to figure out how that could be possible I had to go to the trouble of setting everything up in the debugger, walking through the code . . . and finding out neither was null. Huh? Of course, not at all obvious from reading the code is the fact that getDisplayEligibility()
returns a Boolean
rather than a boolean
, and in this case it was returning null, meaning that the ! operator was throwing the NPE.
Normally, if you tried to apply ! to an object you’d get a compile error, but thanks to the magic of auto-unboxing Java now has all sorts of exciting ways to throw NPEs that you wouldn’t think to find. Right after fixing that bug I ran into another, very similar error:
public boolean isScheduleRate() {
return getPattern().getScheduleRate();
}
Again, getScheduleRate()
actually returns a Boolean
instead of a boolean
, so if it’s null the return statement will NPE. Combined with the way Java implemented the new for loop, that means that instead of an NPE only being possible on the . operator or [] references, you now have to look out for !, return, arithmetic operators like + and -, and for loops.
In GScript we, for better or worse, auto-coerce null to false or 0 depending on the context, which also requires you to understand that that can happen, but at least prevents the sort of hidden NPEs that the current Java approach causes. It probably behaves like you’d expect most of the time and is generally consistent with how other languages behave.
Opinions expressed by DZone contributors are their own.
Comments