1
 @Test public void test(){ Map<String, Integer> a = new HashMap<>(); a.put("x", new Integer(0)); Integer i = a.get("x"); a.put("x", i++); i = a.get("x"); a.put("x", i++); i = a.get("x"); a.put("x", i++); System.err.println(i); } 

The output of the above code is 1 and not 0. I cannot figure out why. Can someone explain whats going on? Some byte code optimizations by Java lead to this state?

2
  • 1
    You increment, so why do you expect 0 to be printed? Commented Sep 6, 2017 at 8:29
  • 1
    Please make use of a debugger. That's an effective way to understand how a code snippet works. Commented Sep 6, 2017 at 8:31

6 Answers 6

4

Because i++ returns i before incrementing i. See my comments:

Map<String, Integer> a = new HashMap<>(); a.put("x", new Integer(0)); // x=0 Integer i = a.get("x"); // i=0 a.put("x", i++); // x=0, i=1 i = a.get("x"); // i=0 a.put("x", i++); // x=0, i=1 i = a.get("x"); // i=0 a.put("x", i++); // x=0, i=1 System.err.println(i); 

Here's the relevant part from the documentation of unary operators:

The increment/decrement operators can be applied before (prefix) or after (postfix) the operand. The code result++; and ++result; will both end in result being incremented by one.

The only difference is that the prefix version (++result) evaluates to the incremented value, whereas the postfix version (result++) evaluates to the original value.

If you are just performing a simple increment/decrement, it doesn't really matter which version you choose. But if you use this operator in part of a larger expression, the one that you choose may make a significant difference.

Sign up to request clarification or add additional context in comments.

Comments

1

Yes, it should be one. Last statement is a.put("x", i++); so you put the value 0 into your Map but then you increment i. If your last statement was i = a.get("x"); you would get 0.

Comments

1

You use post-increment, so the value of i is read first, then incremented.

 @Test public void test(){ Map<String, Integer> a = new HashMap<>(); a.put("x", new Integer(0)); Integer i = a.get("x"); // i is 0 a.put("x", i++); // x = 0; then i increment i = a.get("x"); // i is reset to 0 a.put("x", i++); // x = 0; then i increment i = a.get("x"); // i is reset to 0 a.put("x", i++); // x = 0; then i increment System.err.println(i); // i == 1 } 

Comments

0

Explained inline:

@Test public void test(){ Map<String, Integer> a = new HashMap<>(); a.put("x", new Integer(0)); // Store Integer(0) Integer i = a.get("x"); // Get it a.put("x", i++); // Unbox it, rebox it, store it again (still 0); increment it afterward i = a.get("x"); // Same again a.put("x", i++); // ... i = a.get("x"); // ... a.put("x", i++); // Unbox it, rebox it, store it again (still 0); increment it afterward System.err.println(i); // Show it; contains the *incremented* value } 

Since the value stored is always 0, and you get it at the end and increment it, you end up with 1.

Comments

0

Lets go through this step by step:

 Integer i = a.get("x"); 

i is 0

 a.put("x", i++); 

the "x" in the map doesnt change because you set it to i (=0) and increment after setting it.

 i = a.get("x"); 

Again i gets set to 0 since thats still whats stored in "x"

 a.put("x", i++); 

Same thing as above, i gets set to one only after setting "x" to 0

 i = a.get("x"); 

i =0

 a.put("x", i++); 

Now i is 1 and you print it

 System.err.println(i); 

Comments

0

Your last statement increase i by 1 resulting i = 1.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.