What does the ++ operator do to an Integer? [duplicate]
Asked Answered
R

5

7

Following test case will pass:

@Test
public void assignWrapperTest() {
    System.out.printf("\nassign - %s\n", "wrapper");

    Integer a = 1000;
    Integer b = a;
    System.out.printf("a = %d, b = %d\n", a, b);
    Assert.assertEquals(a, b);
    Assert.assertSame(a, b); // a, b are the same object,

    a++;
    System.out.printf("a = %d, b = %d\n", a, b);
    Assert.assertNotEquals(a, b);
    Assert.assertNotSame(a, b); // a, b are not the same object, any more,
}

So:

  • a is changed by ++.
  • b remains the same.

The questions are:

  • b = a just assign the reference value right, they refer to the same object, at this point there is only one object, right?
  • What ++ operator does on an Integer?
    Since Integer is immutable, does this means ++ created a new Integer object, and assigned it back to the original variable automatically? If that's the case, does that means a now point to a different object?
  • There are 2 objects now? And b still point to the original one ?
Reticular answered 17/12, 2018 at 10:15 Comment(3)
Yes, yes, and yes. You seem to understand this already.Neuroticism
@Neuroticism I am a bit confused at first, I just write a test case and try to figure it out, but I am not very sure is that the real case, so asked the question.Reticular
Your questions have the answers within them. And your intuition is right.Gauss
O
10
a++;

Because a is an Integer, this is the same as:

a = Integer.valueOf(a.intValue() + 1);

does this means ++ created a new Integer object

Maybe, but not necessarily: Integer.valueOf will reuse a cached value; a new value will only be created if outside the cached range (which is at least -128..127).

Ouphe answered 17/12, 2018 at 10:19 Comment(12)
To add to this answer, if a is within that caching range (eg 123), and you do a++ and b++ they will point to the same object.Machiavellian
So, the ++ operator is not atomic, since it has more than 1 operations, right?Reticular
@EricWang correct. It's not atomic for int either.Ouphe
Ok, seems ++ on Integer need 4 individual steps, and on int need 2 steps roughly, anyhow, either are more than 1 step.Reticular
@EricWang the steps for int are read; add one; write.Ouphe
Ok, so 3 steps for ++ on int.Reticular
"Integer.valueOf will reuse a cached value; a new value will only be created if outside the cached range (which is at least -128..127)." - no, even if a new value is created within the cached range it will be a new value, no caching. at least in Java 11Realism
@AndreyM.Stepanov can you provide a code snippet to demonstrate that? The Java 11 docs explicitly states: "This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range."Ouphe
@andy-turner well, if you simply run a = 120; b = a; System.out.printf("a = %d, b = %d\n", a, b); a++; System.out.printf("a = %d, b = %d\n", a, b); the result will be a = 120, b = 120; a = 121, b = 120. If I see it right no putting here to sort of Integer pool or cache. Java 11.0.12Realism
@AndreyM.Stepanov I think you are confused about what incrementing an Integer variable does: it doesn't change anything about the Integer instance the variable points to (nothing can, Integer is immutable. Can you imagine the mayhem if you could make 120 "equal to" 121?). a++ is assigning a new value to a, as described in the answer; this does nothing to the value of the b variable.Ouphe
@andy-turner then what is the meaning of the phrase ""Integer.valueOf will reuse a cached value; a new value will only be created if outside the cached range (which is at least -128..127)."? Could you please provide an example. This cache probably means the same as string pool. Does it mean that if Integer a = 120, and Integer b =120 then a==b. But if Integer a = 130. and Integer b =130 then a != b (which looks like nonsense)Realism
oh, no... Integer a = 120; Integer b = 120; boolean flag = a==b? true : false; a = 200; b = 200; flag = a==b? true : false; first result is true, second is false it's RIDICULOUSRealism
T
4

If we look at the Byte code of a++; It looks something like below:

    9: aload_1
   10: invokevirtual #22                 // Method java/lang/Integer.intValue:()I
   13: iconst_1
   14: iadd
   15: invokestatic  #16                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   18: astore_1

So the instructions are like getting the intValue() of a then increment it then call Integer#valueOf on the incremented value and Integer#valueOf create a new object.

Tedder answered 17/12, 2018 at 10:23 Comment(0)
C
2

Yes.

Integer objects are immutable. But, their references held by are mutable. Integer classes, cache data and reuse them.

Let's see what's happening in your code.

Integer a = 1000; // Let's say it creates a memory block of 4 bytes in heap with address reference &addr_of_val_1000;

Integer b = a; // now, b points to address reference &addr_of_val_1000;

a++; // this creates/fetches a new value 1001 in/from heap with new address reference &addr_of_val_1001; and assignes to variable a

So,

a = 1001 and b = 1000 are not equal. &addr_of_val_1000 != &addr_of_val_1001 (their references are not same anymore)

But, if you add,

b++;

or

b = Integer.valueOf(1001)

before your check, they will be equal and same again.

Cosmetician answered 17/12, 2018 at 10:40 Comment(0)
S
1
  • That is correct. That is the way the JVM works.
  • Yes. a++ effectively does a=a+1 (ignoring the logic to convert it to an Integer). The expression a+1 evaluates to a new int, and that gets assigned to a.
  • Affirmative. The value of b has not been touched by the previous operations, and hence it's still pointing at the same object.
Sinfonietta answered 17/12, 2018 at 10:26 Comment(0)
H
1

The key point here is that Integer is immutable.

  1. If the operand is mutable, like an int, ++ operator just add 1 to the original value in place.

  2. For Integer it is different. By a++, a new instance of Integer is created, and the value of it comes from adding a 1 to the original Integer object which both a and b are pointing to, and then a is re-assigned to this new object. b still refers to the original Integer object, so a and b are not the same now.

Henricks answered 17/12, 2018 at 10:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.