I came across a code snippet on StackOverflow:

Integer a = 42;
Integer b = 42;
Integer c = 555;
Integer d = 555;
System.out.println(a == b); // prints true
System.out.println(c == d); // prints false

Wait, what?

The second comparison evaluating to false makes sense. In Java, when == is used with reference operands, equality means they point to the same object in memory (primitives are compared literally). So c == d should return false, because they’re separate objects in memory (even if representing the same number underneath). But why does the first comparison equate to true?

The answer can be found in the Java Langauge Specification, chapter 5 . Two primitives being autoboxed into references via a boxing conversion may qualify to be cached for optimization purposes. Caching the more commonly used primitive values leads to faster access time, so these certain commonly used primitives are cached:

  • true, false
  • byte or char in the range \u0000 to \u007f
  • int or short in the inclusive range of -128 to 127

So in the snippet above, a == b is true because a and b are between -128 and 127, so when a new Integer a = 42; is created, it simply points to a previously cached Integer object.

Note that this only works when primitive ints are autoboxed to Integers. If two Integer objects are created (not autoboxed from the primitive type)…

Integer e = new Integer(4);
Integer f = new Integer(4);
System.out.println(e == f);

…then the comparison will be false, since both Integer references were explicitly initialized as separate objects.

Interesting stuff!