autoboxing and ++
I just tried to explain autoboxing to a friend from work. coming from C++, he was all enthusiastic to hear about this kind of magic type conversions going on. I wanted to demonstrate him why imho autoboxing was one of the worst ideas that ever made it into the Java language, and wrote this little snippet:
Integer a = 42;
a++;
System.out.println("a is now " + a);
I expected it to print 'a is now 42', because the ++ operator only gets applied to the unboxed int, not the Integer object... however:
a is now 1
can someone explain this completely unexpected and inane behaviour? as hard as I try to figure out why a's intValue should be 1, I can't find an explanation.
btw, += works differently:
Integer a = 42;
a += 1;
System.out.println("a is now " + a);
prints a is now 43
I'm sure this has been discussed here before, but a language really should treat objects as objects and primitives as primitives. adding operators like ++ to objects, that do completely unpredictable stuff, was a really bad idea. just my 2 cents.
[1156 byte] By [
mr.f0xa] at [2007-11-27 11:48:40]

Both snippets produce 43 for me. What compiler are you using? All that autoboxing is, is the compiler generating (for example) Integer.valueOf(int) for you, I wonder if there's a difference between when ECJ and Javac do it, or something
edit: scratch that. Same result using Javac
Message was edited by:
georgemc
> a language really should treat objects as objects and primitives as primitives.
Not entirely convinced
> adding operators like ++ to objects, that do completely unpredictable stuff,
> was a really bad idea
Maybe, if what you said was true, but from what I've seen, it isn't. That said, the implementation of autoboxing isn't without it's problems
public class AutoboxingNPE {
public static void main(String[] args) {
int i = getId();
}
static Integer getId() {
return null;
}
}
> Both snippets produce 43 for me.
Ditto.
~
hmmm...
just tried it with the sun 1.6 java and javac -- and yes, here it spits out 43 both times.
the original example was using Eclipse 3.2.2's internal compiler, so it seems there's a bug in there.
> hmmm...
>
> just tried it with the sun 1.6 java and javac -- and
> yes, here it spits out 43 both times.
> the original example was using Eclipse 3.2.2's
> internal compiler, so it seems there's a bug in there.
That's the compiler I was using, too (ECJ 3.2.2) so, no, it appears not
I also tried using Sun's Javac 1.5_06
now I'm confused.
I was using the scapbook page to run the examples. there, it spits out 1.
howver, if compile and run it as a normal class: 43.
> now I'm confused.
>
> I was using the scapbook page to run the examples.
> there, it spits out 1.
>
> howver, if compile and run it as a normal class: 43.
What's confusing about it? The actual, real compilers behave as they should
> I was using the scapbook page...
Can't say I've ever used that "feature". But sure enough, it gives the results you describe. I think I'll go back to not using it... ;o)
~
> What's confusing about it? The actual, real compilers
> behave as they should
well, I was assuming that the scapbook page uses an 'actual, real compiler' and code there produces the same result as code in a real class, but obviously I was mistaken - lesson learned!
thanks to everyone for your answers.
> > What's confusing about it? The actual, real
> compilers
> > behave as they should
>
> well, I was assuming that the scapbook page uses an
> 'actual, real compiler' and code there produces the
> same result as code in a real class, but obviously I
> was mistaken - lesson learned!
>
> thanks to everyone for your answers.
I expect (but haven't bothered checking, to be fair) that whatever evaluates expressions in the scrapbook is out-of-date, ie not Java5 compliant. I've never used it myself, don't really see the point
it is working fine for both and giving the same result.
> it is working fine for both and giving the same
> result.
:-) see rest of thread!
> it is working fine for both and giving the same result.
Not when evaluated in the Eclipse scrapbook page, as described.
~
I'm saddened that yawmark didn't take the chance to generate Java bytecode for this, because it's really wacked.
public static void foo()
{
Integer a = 12;
a++;
}
becomes
public static void foo();
Code:
0:bipush 12
2:invokestatic#2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5:astore_0
6:aload_0
7:astore_1
8:aload_0
9:invokevirtual#3; //Method java/lang/Integer.intValue:()I
12: iconst_1
13: iadd
14: invokestatic#2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
17: dup
18: astore_0
19: astore_2
20: aload_1
21: pop
22: return
It's interesting to me that this takes up 3 slots on the stack, and doesn't use the iinc operator. So here's what happens:
* The Integer gets created, and stored in slot 0 (since this is a static method, slot 0 is available for local variables).
* It then gets loaded, and stored again in slot 1, preserving the original value.
* Then loaded again, converted to int (which remains on the stack), and then an integer add (again, on the stack)
* The result of that addition gets converted back to Integer, and stored in slot 0. And also, for some unknown reason, in slot 2.
* The original value is pushed on the stack, but then we reach the end of expression so it gets popped off.
By comparison, here's the code with int
public static void foo();
Code:
0:bipush 12
2:istore_0
3:iinc0, 1
6:return
