Integer缓存池

前言

前面我们了解了==主要用来比较两个对象类型的内存地址,但在平时写代码时,我们会不会碰到这样的现象:对于对象类型,当两个比较对象为某些值时,为什么使用==结果也为true呢?其实这都是Integer缓存池的功劳。下面我们将介绍这个强大的缓存池。


一、Integer缓存池是什么?

首先,我们先来看一小段代码------

代码示例:

java 复制代码
public class IntegerCacheDemo {
    public static void main(String[] args) {
        Integer a = 127;
        Integer b = 127;
        System.out.println(a == b); 

        Integer c = 128;
        Integer d = 128;
        System.out.println(c == d); 
    }
}

运行结果:

如图,我们创建对照组1和对照组2,两个对照组均使用Integer创建对象,由==进行比较,即比较两者的内存地址。在对照组1中,a与b 的值均为127,对照组2中,c与d 的值均为128。由运行结果我们可知,两个对照组中,对照组1的比较结果为true,表明a,b所指向的地址相同;但在对照组2中,结果表现为false,即c,d所指向的地址不同。造成这种情况的源头就是Integer缓存池。


二、Integer缓存池的底层原理

在JDK中,当我们写下Integer a = 127;时,实际上发生了自动装箱。java编译器会将其转换为:

java 复制代码
Integer a = Integer.valueOf(127);

重点在于Integer.valueOf(inr i)方法。我们一起来看看源码:

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

由源代码可知:

如果传入的整数i在缓存池的范围内,则直接从IntegerCache.cache数组中返回缓存对象。否则就建立一个新的Integer对象。

这就可以解释为什么127时a==b为true,而128时c==d为false。即127为Integer缓存池可保存的最大数据。


三、IntegerCache内部类源码

那么IntegerCache到底是怎么实现的呢?我们继续看源码:

java 复制代码
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        int h = 127;
        String propValue = sun.misc.VM.getSavedProperty(
            "java.lang.Integer.IntegerCache.high");
        if (propValue != null) {
            int i = Integer.parseInt(propValue);
            i = Math.max(i, 127);
            h = Math.min(i, Integer.MAX_VALUE - (-low) - 1);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for (int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }
}

从源码我们可知:

1.默认缓存范围是-128,127。

2.这个上限可以通过JVVM参数-Djava.lang.Integer.IntegerCache.high=xxx来修改。

3.缓存池在类加载时就会被初始化,里面预先放好了从-128到127的Integer对象。


四、验证缓存池的效果

我们来写一段测试代码:

java 复制代码
public class IntegerCacheTest {
    public static void main(String[] args) {
        Integer x = Integer.valueOf(127);
        Integer y = Integer.valueOf(127);
        System.out.println(x == y); // true

        Integer m = Integer.valueOf(200);
        Integer n = Integer.valueOf(200);
        System.out.println(m == n); // false
    }
}

如果我们在启动时加上参数:

java 复制代码
java -Djava.lang.Integer.IntegerCache.high=200 IntegerCacheTest

结果将为:

java 复制代码
true
true

这是因为缓存池的上限被扩大到了200。


五、Integer缓存池的作用

1.性能优化:Integer时不可变对象,如果每次都新建会浪费内存和增加GC压力。

2.节省空间:小整数在程序中使用非常频繁,例如循环、数组下标、计数器等。缓存池能复用这些对象。

3.提高运行效率:避免了频繁的对象创建与销毁。

六、注意事项

1.不要用==比较数值

==比较的是地址是否相同,在缓存范围内,==可能是true,但范围之外一定是false。正确的做法是equals()。

2.警惕自动装箱陷阱

java 复制代码
Integer a = 127;  // 自动装箱,相当于 Integer.valueOf(127)
Integer b = 127;
System.out.println(a == b); // true

Integer c = 128;  // 自动装箱,相当于 Integer.valueOf(128)
Integer d = 128;
System.out.println(c == d); // false

总结

Integer 缓存池是 Java 中一个经典的性能优化机制,它让小整数对象得以复用,避免频繁创建。但同时也容易让人掉进 == 和 equals 的陷阱。

相关推荐
半摆烂日常21 分钟前
手机表单的左滑操作:触摸事件的处理细节
大数据·开发语言·人工智能·智能手机·https·c#
星夜离尘5632 分钟前
MATLAB滑动RMS如何接报警:窗口未满和缺样不能当成正常
开发语言·matlab
SL_staff35 分钟前
周报越厚问题越拖?用结构化执行机制让周报回归决策价值
java·spring cloud·开源
开开心心就好39 分钟前
白天晚上自动调蓝光,护眼工具亮度可调
服务器·开发语言·算法·pdf·ocr·intellij-idea·idea
张张123y40 分钟前
后端第十一课:RAG 落地实战(从 0 到 1 接上私有知识库,并设计一个好用的 RAG)
开发语言·人工智能·python·机器学习·fastapi·rag
梅梅绵绵冰42 分钟前
JVM虚拟机
java·开发语言·jvm
golang学习记1 小时前
Python vs Go:2026年到底该怎么选
java·vscode·python·golang·pycharm·goland
Shaoshing1 小时前
消息顺序
java·开发语言
云水初1 小时前
【项目篇】基于LanGraph的自动处理客服邮件的 Agent汇总
开发语言·笔记·python·学习·fastapi·langgraph
茉莉玫瑰花茶1 小时前
GO [ 内存与变量逃逸分析 ]
开发语言·后端·golang