Fundamentals 4 min read

Understanding Java Integer Caching and the == Operator

This article explains why comparing Integer objects with == yields false for large values but true for small values due to Java's internal IntegerCache, demonstrates the caching mechanism with code examples, and shows how reflection can manipulate the cache, highlighting memory optimization considerations.

Java Captain
Java Captain
Java Captain
Understanding Java Integer Caching and the == Operator

This is an interesting discussion topic.

If you run the following code:

Integer a = 1000, b = 1000; 
System.out.println(a == b);//1
Integer c = 100, d = 100; 
System.out.println(c == d);//2

You will get:

false
true

Basic knowledge: we know that if two references point to the same object, == indicates they are equal. If they point to different objects, == indicates they are not equal, even if their contents are the same.

Therefore, the latter statement should also be false.

This is the interesting part. If you look at the Integer.java class, you will find an internal private class IntegerCache.java that caches all integer objects in the range -128 to 127.

Thus, all small integers are cached internally, and when we declare something like:

Integer c = 100;

the JVM actually does:

Integer i = Integer.valueOf(100);

Looking at the valueOf() method, we can see:

public static Integer valueOf(int i){
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

If the value is within -128 to 127, it returns an instance from the cache.

So…

Integer c = 100, d = 100;

both references point to the same object.

That is why we write:

System.out.println(c == d);

and we get true .

Now you may ask why this cache is needed. The logical reason is that small integers are used far more frequently than large ones, so reusing the same underlying object reduces memory consumption.

However, the cache can be misused via the reflection API.

Run the following code and enjoy its charm:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Class cache = Integer.class.getDeclaredClasses()[0]; //1
    Field myCache = cache.getDeclaredField("cache"); //2
    myCache.setAccessible(true); //3
    Integer[] newCache = (Integer[]) myCache.get(cache); //4
    newCache[132] = newCache[133]; //5
    int a = 2;
    int b = a + a;
    System.out.printf("%d + %d = %d", a, a, b);
}

If this article helped you, please don’t hesitate to give a like, thank you!

JavaMemory Optimizationreflectioninteger cachingReference Equality
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.