2

In Herbert Schildt's "Java: The Complete Reference, 9th Edition", there's an example that kinda baffles me. Its key point that i can't comprehend could be summed up to the following code:

class Test {
    public static void main (String args[]) {               
        Integer i1 = 6;
        Integer i2 = 6;

        Integer i3 = 6;
        Integer i4 = (args.length + 1) * 6;

        if (i1 == i2) System.out.println("WTF");
        if (i3 == i4) System.out.println("Super WTF!!!");
    }
}

To my surprise, the result of compiling and executing such code using JDK 8 update 40 is as follows:

WTF
Super WTF!!!

All the Java books, manuals and other informational resources that i've seen state that the equality operator (==), when used to compare objects, simply matches their reference values. So, if two object variables refer to distinct instances, then the == operator returns false, even if the internal contents of those objects are the same. Which is quite different from the behavior expressed by the example above.

While checking SO for similar questions, i found a somewhat related one, which is about comparing String objects using ==. There, an interesting feature of Java called interning was mentioned. Apparently, all the string literals and compile-time string constants are sort of "cached" by JVM, so that, for example, multiple String references initialized with the same string literals actually point to the same object.

But here we deal with numeric values and Integer objects. Also, one of the variables, i4, is initialized using a number of command line arguments supplied to the program, which is definitely a run-time information. Yet, == still finds it equal to i3.

So, given all the above, how exactly is the equality operator supposed to work in Java? Does it, or does it not, inspect the objects' contents when comparing them?

Thanks!

Community
  • 1
  • 1
Semisonic
  • 1,152
  • 8
  • 21
  • 1
    Java caches `Integer` objects for numbers between `-128` to `127`. So unless you use `new Integer()`, you're going to get the cached object. – Rohit Jain Mar 08 '15 at 11:05
  • Read first answer : http://stackoverflow.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127 – pL4Gu33 Mar 08 '15 at 11:06
  • @pL4Gu33, thank you. It's the first time I've heard about such caching technique. – Semisonic Mar 08 '15 at 11:11

3 Answers3

4

Integer objects are cached as mentioned by the Javadocs of Integer#valueOf(int):

This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

The statement Integer i4 = (args.length + 1) * 6; calls Integer#valueOf(int) which returns the cached instance. On the other hand, if you use Integer i4 = new Integer((args.length + 1) * 6);, the reference equality will return false.

M A
  • 71,713
  • 13
  • 134
  • 174
2

I think the example shows us how java int pool is working. So in the i4 case if you provided no arguments on runtime the result is 6. Now the int pool kicks in and uses the i1 value which is part of the -128 to to 127 int pool. So on an object level they really equal and that's what == is all about.

Hannes
  • 2,018
  • 25
  • 32
1

When you autobox an int, you're internally calling Integer.valueOf(int), which according to the documentation may return cached values. So it makes perfect sense that you're seeing reference equality.

More generally, you should never assume two references are distinct unless you explicitly constructed them. And for the record, string interning is available at runtime as well, through the String.intern() method.

shmosel
  • 49,289
  • 6
  • 73
  • 138
  • Thank you for emphasizing the point that references should not be assumed distinct unless explicitly made so. – Semisonic Mar 08 '15 at 11:22