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 ?
Lii
  • 11,553
  • 8
  • 64
  • 88
Eric
  • 22,183
  • 20
  • 145
  • 196
  • 6
    Yes, yes, and yes. You seem to understand this already. – khelwood Dec 17 '18 at 10:17
  • @khelwood 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. – Eric Dec 17 '18 at 10:19
  • Your questions have the answers within them. And your intuition is right. – sid-m Dec 17 '18 at 10:19

5 Answers5

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

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • 4
    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. – Mark Dec 17 '18 at 10:23
  • So, the `++` operator is not atomic, since it has more than 1 operations, right? – Eric Dec 17 '18 at 10:29
  • 2
    @EricWang correct. It's not atomic for `int` either. – Andy Turner Dec 17 '18 at 10:32
  • Ok, seems `++` on `Integer` need 4 individual steps, and on `int` need 2 steps roughly, anyhow, either are more than 1 step. – Eric Dec 17 '18 at 10:35
  • 1
    @EricWang the steps for `int` are read; add one; write. – Andy Turner Dec 17 '18 at 10:38
  • Ok, so 3 steps for `++` on `int`. – Eric Dec 17 '18 at 10:39
  • "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 11 – Andrey M. Stepanov Mar 05 '23 at 15:14
  • @AndreyM.Stepanov can you provide a code snippet to demonstrate that? The Java 11 docs [explicitly states](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Integer.html#valueOf(int)): "This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range." – Andy Turner Mar 07 '23 at 07:13
  • @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.12 – Andrey M. Stepanov Mar 08 '23 at 17:05
  • @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. – Andy Turner Mar 09 '23 at 08:29
  • @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) – Andrey M. Stepanov Mar 09 '23 at 22:33
  • 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 RIDICULOUS – Andrey M. Stepanov Mar 09 '23 at 22:39
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.

Amit Bera
  • 7,075
  • 1
  • 19
  • 42
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.

Sridhar
  • 1,518
  • 14
  • 27
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.
bohemian
  • 149
  • 2
  • 17
0

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.

ZhaoGang
  • 4,491
  • 1
  • 27
  • 39