Full-stack open-source component framework to quickly and consistently develop and maintain Java web applications
entries for Geert Bevin > 2004 > 3 > 11 > The dangers of auto-unboxing
JDK 1.5 provides a collection of very nice language additions and I've become an early adopter of many of them. I recently began having my doubts about auto-unboxing of reference variables though.
Consider the following class:
class AutoUnbox<T>
{
private T mResult;
T getResult()
{
/* do some stuff and return a result */
return mResult;
}
}
and then some code that uses it:
AutoUnbox<Boolean> a = new AutoUnbox<Boolean>();
if (true == a.getResult())
{
System.out.println("success");
}
This looks quite harmless, doesn't it? Well you have a totally invisible NullPointerException that is lurking in this code. If the getResult() method returns null, the conversion to a primitive will throw a NullPointerException. The biggest issue with this is that it happens behind the scenes. I'm used to thinking about references that might be null when I call a method upon them. As soon as I type the dot operator, my mind thinks about the context and considers if I shouldn't perform a nullcheck first. With auto-unboxing, there is nothing that indicates that you should be careful. It could literally happen anywhere.
NullPointerException
getResult()
null
Imho JDK 1.5 is wrong about this and instead of throwing the NPE it should return an unintialized primitive, just as null is the uninitialized value for a reference.
I mean, look at this code:
public class Uninit
{
int test;
boolean bool;
public static void main(String[] args)
{
new Uninit().method();
}
public void method()
{
System.out.println(test);
System.out.println(bool);
}
}
It returns 0 and false which means that there are default values defined for unitialized primitives. To me, when thinking about unboxing a null reference to a primitive I always expected to get this 'empty' value, not a NPE.
0
false
I think I'm going to submit a bugreport to Sun about this, what do you think?
I think you are right. Please do submit a bug report.
As I understand it, this was something that the people working on JSR-201 spent quite a bit of time discussing and working on.
See, for example, Joshua Bloch's preview of 1.5 features from almost a year ago:
."
Uwyn, you should definitely send an email about this to the appropriate email address, which is jsr-201-comments@jcp.org . They do read comments and take them seriously. I get the impression the JSR201 folks couldn't find strong reasons for or against the unboxing null question, so your example might tip the balance.
Yeah Josh, I got a better suggestion it's just that you are not interested in listening to it! Autoboxing is a bandage over the real problem. The real problem is obvious. primitives need to be first class objects and not primitive. The design anti-patterns to prove this are littered all throughout the language and the JDK libraries. For example, I point to java.lang.Math. This abstract final class acts as a shelter to behavior that would otherwise be homeless. If primitives were represented as first class objects, this class would not be needed.
And what about throwing something like UnintializedPrimitiveException which would be a SUBCLASS of NullPointerException? It's a compromise, but it would give you more information about the cause of error.
same behavior in c#
auto-boxing / unboxing turns out to be obnoxious. For example, consider what your code must look like if you're extracting from a Map.... ugly
Autoboxing for a null value should always throw an exception? Why? null has no meaning for primitives, be they boolean, int, or anything else. By using autoboxing you are saying to the compiler "please convert this primitive from a primitive to an object and back". Since there is no mapping from null back to a primitive it always indicates you have done something wrong. Autoboxing is there simply to save you typing, not to change the rules of type casting.
rifers.org v0.9.8 - © 2001-2007 the RIFE team