Tuesday, August 07, 2007

Autoboxing == !Cool

So you're finally getting used to the idea of Java 5's "feature" of converting between primitive types and their corresponding object wrappers (e.g., int -- Integer). You're getting to the point where you kind of trust it. You're even getting to the point where you kind of rely on it. Life is good.

Then you go too far and try something weird and exotic like, oh, I don't know:

int sucker = thisMethodReallyReturnsAnIntegerNotAnInt();

No squiggly red line in your Eclipse editor. Cool! That must mean this will work! Because Java has static typing, and you can count on that! Yea you!

The problem is, it will work. It will work very nearly all the time. It will work until your method returns a null instead of an actual Integer. At which point you'll get a NullPointerException buried in your Struts 2 / OGNL / JSP project's Eclipse console stack trace, followed by a two-hour detour into the debugger wondering what the heck is going on. I mean after all, your code compiled, right? It worked for the first hour, right? Static typing is good, right? Autoboxing works, right?

Not that you're bitter.

7 comments:

Billy Bob Bain said...

I feel your pain!

unboxing and the elusive npe

Cedric said...

We carefully considered the alternative (returning a default value for the type, another concept we would have had to invent) but it was obvious to everyone that this would be even worse.

And come on, a NullPointerException takes seconds to pinpoint.

David Rupp said...

Yeah, I agree there would've been no way to return some distinguished value that would be guaranted not to cause some subtle bugs in someone's code.

And you're right, it *should* take only seconds to pinpoint an NPE, which is partly why I feel so stupid about it. In my defense, it was presented as a JSP/EL/OGNL "unable to determine a value for expression ${x}". It wasn't even clear that it was an NPE at first.

But I think my point about not immediately suspecting the assignment to an int -- which didn't have any explicit object references on the right hand side -- is valid.

Given that Sun was dead set on adding autoboxing to the language, I agree that there are worse ways you could have done it. But having done it, you've broken what we've been trained to expect from static typing.

Peter Lawrey said...

You could use IntelliJ where you can declare your method like:

@Nullable Integer thisMethodReallyReturnsAnIntegerNotAnInt() {
return null;
}

Then you will get a warning in your IDE if you try to deference it.

willCode4Beer said...

Think you are missing the fundamentals.
Ok, so you don't like:
int sucker = thisMethodReallyReturnsAnIntegerNotAnInt();
because of a possible null pointer.
int sucker = thisMethodReallyReturnsAnIntegerNotAnInt().intValue();
can do the same.

Autoboxing does not remove the need to do checking in cases where you don't have control of the return value.

Besides, what should the "default" be when the value is null? Everybody is going to have a different opinion of that.

David Rupp said...

@willcode4beer: I'm pretty sure I get it, especially now that I know what to look out for. My problem was that I'm used to pre-autoboxing, when the expression wouldn't compile; the compiler would have told me that the method really returns an object, not a primitive. When I see 'int' on the left side of a statement, I assume that the right side is an 'int' (or other -- primitive -- int-compatible).

Just takes some getting used to, and I'm pretty sure I'm capable. But it does play hob with a reasonable intuition about the type safety that Java is supposed to guarantee.

Thanks for your input.

jb said...

Well you may just tweak your eclipse to give warning/error on autoboxing.