Understanding Integer Caching in Java: Why 128 == 128
Can Be False
If you’ve ever worked with Java, you might expect that comparing two equal numbers with ==
would always return true
. But have you ever encountered a scenario where 128 == 128
results in false
? Strange, right? Let's dive into the reason behind this behavior, known as Integer Caching, and understand how it affects the way Java handles certain values.
Integer Caching: The Magic Behind 1 == 1
In Java, when you compare small numbers like 1 == 1
, the comparison works as expected and returns true
. However, things get tricky when you move to larger numbers, such as 128
. Here's a small code snippet that illustrates the issue:
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false
Integer x = 1;
Integer y = 1;
System.out.println(x == y); // true
Wait, why does 128 == 128
return false
while 1 == 1
returns true
? The answer lies in Java’s Integer Caching mechanism.
The Mechanism: How Integer Caching Works
Java automatically caches Integer objects within a specific range to save memory and improve performance. By default, Integer values between -128 and 127 are cached. This means that when you assign an Integer within this range, instead of creating a new object every time, Java reuses an existing cached object.
In this case, both x
and y
refer to the same cached object in memory, so x == y
returns true
. Java doesn't create two separate objects for the value 1
; instead, it points both x
and y
to the same memory location.
Why 128 == 128
Fails
The default caching range in Java only applies to numbers from -128 to 127. Any Integer values outside this range, such as 128
, are not cached. This means that:
Here, Java creates two distinct objects for a
and b
, even though both hold the value 128
. When you compare a == b
, Java compares the memory references, not the actual values. Since a
and b
are two separate objects in memory, a == b
returns false
.
The Difference Between ==
and .equals()
In Java, the ==
operator compares references, meaning it checks whether two variables point to the same object in memory. On the other hand, the .equals()
method compares the values inside the objects, making it a more appropriate choice when comparing numbers.
Let’s tweak the earlier code example:
Integer a = 128;
Integer b = 128;
System.out.println(a.equals(b)); // true
Now, a.equals(b)
returns true
because .equals()
compares the actual values stored in the Integer objects, and both a
and b
hold the value 128
.
Integer Caching Range
Java's caching behavior applies only to the range -128 to 127 by default. You can even customize this range using the JVM option -XX:AutoBoxCacheMax=size
. However, in most cases, this default range is sufficient for optimizing memory usage in typical applications.
An Example: Exploring Memory Allocation
To further understand how caching works, we can examine the hash codes of Integer objects:
Integer i = 1;
Integer j = 1;
System.out.println(System.identityHashCode(i)); // HashCode of i (cached object)
System.out.println(System.identityHashCode(j)); // HashCode of j (same cached object)
System.out.println(i == j);
Integer x = 128;
Integer y = 128;
System.out.println(System.identityHashCode(x)); // HashCode of x
System.out.println(System.identityHashCode(y)); // HashCode of y
System.out.println(x == y);
292938459
292938459
true
212628335
2111991224
false
For values within the cached range, like 1
, the identityHashCode()
will return the same value for e
and f
because they refer to the same cached object. But for values outside the range, such as 128
, Java allocates separate memory locations, resulting in different hash codes for c
and d
.
Differences between int and Integer in Java
In Java, int
is a primitive data type, meaning no object is created when you use it. The value is stored directly in the stack memory during compile time. On the other hand, Integer
is a class in Java. So when you declare Integer a = 100;
, a
becomes an object of the java.lang.Integer
class. The value 100
is stored in an Integer object, which gets allocated in the heap memory at runtime.
Key Takeaway: Always Use .equals()
for Comparisons
Java’s Integer caching mechanism is a clever optimization, but it can lead to unexpected results when comparing numbers using ==
. For numbers in the -128 to 127 range, ==
works as expected because of caching. However, for numbers outside this range, always use .equals()
to compare the actual values, unless you specifically want to compare memory references (which is rare).
Happy coding❤️!
References : -
https://medium.com/@tecnicorabi/why-1-1-is-true-but-128-128-is-false-in-java-4ea544e83eef
https://medium.com/@ankitkhatriofficial/everything-about-java-integer-caching-b5c752a91393