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]
# 1

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

georgemca at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 2

> 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;

}

}

georgemca at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 3

> Both snippets produce 43 for me.

Ditto.

~

yawmarka at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 4

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.

mr.f0xa at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 5

> 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

georgemca at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 6

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.

mr.f0xa at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 7

> 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

georgemca at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 8

> 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)

~

yawmarka at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 9

> 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.

mr.f0xa at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 10

> > 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

georgemca at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 11

it is working fine for both and giving the same result.

Prem_Sa at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 12

> it is working fine for both and giving the same

> result.

:-) see rest of thread!

georgemca at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 13

> it is working fine for both and giving the same result.

Not when evaluated in the Eclipse scrapbook page, as described.

~

yawmarka at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...
# 14

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

kdgregorya at 2007-7-29 18:20:37 > top of Java-index,Java Essentials,Java Programming...