Thursday, July 12, 2007

Auto Unboxing in Java

There has been a lot of discussion among my colleagues about the evilness of auto unboxing in Java. The evilness can be easily demonstrated:

int x = null;
if (x == 0) {}; // this throws a NullPointerException

The argument on why this is evil is that in pre-Java 1.5 days, developers would have written the following equivalent instead:

if (x.intValue() == 0) {}; // still throws a NullPointerException

When they typed the ".intValue()" they would realize that they needed to add a null check:

if (x!=null && x.intValue() == 0) {}; // No NPE here

The other case for evilness is imagine somebody created the following API:

public void foo(Integer i);

And then changed the signature to:

public void foo(int i);

In pre-Java 1.5 days, any clients of foo() would have compilation errors, thus alerting "people" that they needed to add null-checking code. With Java 1.5+, there would be no compilation errors, so there is obviously a chance for Something Bad To Happen.

You might have noticed that I've been distancing myself from these arguments. I don't really buy them and tend to argue the other side. Auto unboxing is just a new language feature that you had better understand before you use it. If you understand it, then of course you will write

if (x!=null && x == 0) {}; // no NPE here either

And you will change your API as:

@Deprecated public void foo(Integer i);
public void foo(int i);

The real antidote is developer knowledge and good testing to catch the corner cases.

A lot of my colleagues would like an option in Eclipse to cause a compiler error whenever auto unboxing could cause problems. IntelliJ IDEA gives a warning. Maybe there's an option for it to give an error instead of a warning.

I remember when unboxing was a JSR. It was definitely the most controversial part of JSR 201. Many people argued for default values to avoid the NPE problem. That would have been horrible, IMO. Of course C# has the advantage here. That's because they had boxing/unboxing from day one. You can't write Double x = null; --- it won't compile. You can do something like Object x = null; Double d = (Double) x; ... but you're really trying to throw an exception at that point.

1 comment:

Android app developer said...

This is one of the Important and knowledgeable post.I like your blog Instruction.supper.