为什么 Integer a = 100, b = 100 时 a == b为 true,但改成 200 就变成 false?背后的机制是什么?

验证

运行代码

java 复制代码
public class Main{
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);
        Integer c = 200;
        Integer d = 200;
        System.out.println(c == d);
    }
}

运行结果

out 复制代码
true
false

原因

java 复制代码
Integer a = 100;

这段代码是自动装箱/拆箱机制,本质上是调用Integer.valueof(100)

给出源码

java 复制代码
@IntrinsicCandidate
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.low到IntegerCache.high之间的时候返回缓存池里面的值,否则返回新值,我们再具体看一下IntegerCache的源码。

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

    @Stable
    static final Integer[] cache;
    static Integer[] archivedCache;

    static {
        int h = 127;
        String integerCacheHighPropValue =
            VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                h = Math.max(parseInt(integerCacheHighPropValue), 127);
                h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
            }
        }
        high = h;
        CDS.initializeFromArchive(IntegerCache.class);
        int size = (high - low) + 1;
        if (archivedCache == null || size > archivedCache.length) {
            Integer[] c = new Integer[size];
            int j = low;
            int archivedSize = (archivedCache == null) ? 0 : archivedCache.length;
            for (int i = 0; i < archivedSize; i++) {
                c[i] = archivedCache[i];
                assert j == archivedCache[i];
                j++;
            }
            for (int i = archivedSize; i < size; i++) {
                c[i] = new Integer(j++);
            }
            archivedCache = c;
        }
        cache = archivedCache;
        assert IntegerCache.high >= 127;
    }
    private IntegerCache() {}
}

也就是说如果数值在[-128,127]之间,就返回缓存池里面已经存在的对象,否则创建一个新的Integer对象。

上面代码,a和b都是100,在[-128,127]之间,都是缓存池里面的同一个对象,指向同一地址,c和d是200,不在[-128,127]之间,会返回新的,指向不同地址。

面试

在 Java 中,Integer 对象的比较行为受缓存机制影响。对于值在 [-128, 127] 范围内的 Integer,由于缓存池的存在,多个 Integer 实例会指向同一个对象,导致 == 比较为 true。而超出此范围的 Integer 则会返回新的对象,因此 == 比较为 false

相关推荐
小小de风呀11 小时前
de风——【从零开始学C++】(五):内存管理
开发语言·c++
ooseabiscuit11 小时前
Laravel6.x核心优化与特性全解析
android·开发语言·javascript
折哥的程序人生 · 物流技术专研11 小时前
Java面试85题图解版(一):基础核心篇
java·开发语言·后端·面试
AllData公司负责人11 小时前
通过Postgresql同步到Doris,全视角演示AllData数据中台核心功能效果,涵盖:数据入湖仓,数据同步,数据处理,数据服务,BI可视化驾驶舱
java·大数据·数据库·数据仓库·人工智能·python·postgresql
Hello.Reader11 小时前
算法基础(十)——分治思想把大问题拆成小问题
java·开发语言·算法
一只大袋鼠11 小时前
JavaWeb四种文件上传方式(下篇)
java·开发语言·springmvc·javaweb
TE-茶叶蛋12 小时前
深入研究 yudao-framework 模块:Java 编程能力提升指南
java·开发语言
逻辑驱动的ken12 小时前
Java高频考点场景题24
java·开发语言·面试·职场和发展·求职招聘
兔小盈12 小时前
多线程-(五)线程安全之内存可见性
java·开发语言·多线程
CeshirenTester13 小时前
LangChain的工具调用 vs 原生Skill API:性能差在哪儿?
java·人工智能·langchain