This article focuses on a low level detail of the JVM and on why it can be extremely dangerous, especially for beginner Java developers. It can be an interesting piece of information even if you are a bit more experienced. The topic we are going to dive into is objects comparison in Java, why the
== operator does not work when comparing objects, and why sometimes it actually works.
Boxed primitives can be weird
How do you compare two boxed primitives such as
Integer a = 1; Integer b = 1; if (a == b) /** Do something */
Any java book or teacher will prevent you from doing the above because of the behaviour of the Java
== operator which only compares object instances and not objects values. Since
b are different instances of the
Integer class the code above will not work. We must use the
equals() method to compare objects values in Java.
So far so good right? Nope. The code above works like a charm. The
if block is executed. That’s weird. It gets worse, let’s change the values:
Integer a = 1000; Integer b = 1000; if (a == b) /** Do something */
If we run this code we notice that this time the
if block is not executed. Weird. So why does this code behave in a different way just by changing the values of
The truth about boxed primitives
The secret is called interning. It is a rather obscure optimisation strategy. It is basically a cache. Instead of creating new objects over and over again, the JVM stores, or interns, some frequently used instances, so they are already there when requested. In this example this is happening for
Long instances with values ranging from -128 to 127, however the range can be different depending on the specific JVM implementation.
When we create an
Integer instance by assigning a value between -128 and 127 the JVM does not create a new
Integer instance, it simply looks it up in its cache and returns that instance. Therefore when creating two or more instances of the
Integer class with values inside the interning range the
== operator will work, simply because we are comparing two references to the same instance.
Note that the interning mechanism does not apply if we explicitly create two instances of the
Integer class using the
Integer a = new Integer(1); Integer b = new Integer(1); if (a == b) /** Do something */
This code works as expected, the
== evaluates to
The interning mechanism can be an extremely dangerous pitfall that can trick developers, especially beginners, into believing that the Java
== operator works on
Long as well as with primitives int and long. And sometimes it will, but not for the reason you think of. So, be safe, just use