Why 1==1 is true but 128==128 is false in Java

Mukul kumarMukul kumar
4 min read

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

https://www.geeksforgeeks.org/java-integer-cache/

11
Subscribe to my newsletter

Read articles from Mukul kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mukul kumar
Mukul kumar

Hey! I am a software Engineer who is skilled in Java backend and has a good understanding of Spring Boot and Quarkus Frameworks