4

When comparing an Integer object and a constant value, does Java box the value or unbox the Integer object?

Based on what I have read, "==" is a reference comparison, therefore it's only logical to assume that Java boxes the constant to perform the reference comparison between the objects. Yet, the below test code seems to be give contradictory results.

Integer v1 = 1000;
Integer v2 = 1000;
boolean b1 = v1 == 1000; //True.
boolean b2 = v1 == v2; //False. Proof that 1000 boxes to new object and is not fetched from cache.

So how does object vs constant value comparison using == works in Java? Does the operator compare by value in this case?

Amrish Kumar
  • 308
  • 3
  • 12
  • using `Integer::valueOf(1000)` give you a chance of some caching. – John3136 Mar 04 '20 at 06:46
  • IIRC, JLS requires for only 256 values to be cached by default i.e from -128 to 127. Also, `Integer v1 = 1000;` calls the `value0f` method internally. – Amrish Kumar Mar 04 '20 at 06:51
  • It is guaranteed to cache -128 to 127 but may cache more. If you use `valueOf` it may cache, it may not - at least there is a chance! – John3136 Mar 04 '20 at 22:18
  • I need not explicitly use the `valueOf` method. *Boxing internally calls that method*. `Integer v1 = 1000;` and `Integer v1 = Integer.valueOf(1000);` are the same, I know this from using the debugger. – Amrish Kumar Mar 05 '20 at 05:27

2 Answers2

3

What you call "a constant value" is an int literal, so its type is int.

JLS 15.21.1 says:

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands.

In your v1 == 1000 test, 1000 is of numeric type and v1 is convertible to numeric type, so binary numeric promotion is performed.

JLS 5.6.2 (Binary numeric promotion) says:

If any operand is of a reference type, it is subjected to unboxing conversion

Hence, the Integer operand - v1 - is unboxed to an int and a comparison of two ints is performed. Therefore the result of the comparison is true.

When you compare two reference types - v1 == v2 - no unboxing takes places, only the references are compared, as written in JLS 15.21.3:

If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.

Since 1000 is too large to be cached by the Integer cache, b1 and b2 are not referencing the same instance, and therefore the result of the comparison is false.

Eran
  • 387,369
  • 54
  • 702
  • 768
0

Integer pools are same to string pool but it caches value if integer objects in the range -128 to 127 So when you try to assign a value in this range to a wrapper object, the boxing operation will invoke Integer.valueOf method and in turn it will assign a reference to the object already in the pool.

but, if you assign a value outside this range to a wrapper reference type, Integer.valueOf will create a new Integer object for that value. And hence, comparing the reference for Integer objects having value outside this range will give you false

So in your case

Integer v1 = 1000;
Integer v2 = 1000;
boolean b1 = v1 == 1000; //True.
boolean b2 = v1 == v2; // out of range so it will false but if you use 127 instead of 1000 then it will true.

check the documentation here

Negi Rox
  • 3,828
  • 1
  • 11
  • 18