【面试题1】128陷阱、==和equals的区别

128陷阱

核心定义

128陷阱是java中Integer包装类自动装箱时的一个典型现象。

当通过自动装箱创建-128-127范围内的Integer对象时,会复用常量池中的缓存对象;超出该范围时,会创建新的对象。

直接用==比较超出范围的Integer对象时,会出现"值相等但==判断为false"的情况。

这就是128陷阱,本质是-128-127的缓存机制导致的。

原理分析

java为了优化性能,在Integer类中维护了一个IntegerCache缓存池,默认存储-128-127的Integer对象:

  1. 当执行Integer a = 100;(自动装箱)时,底层调用Integer.valueOf(100),直接返回缓存池中的对象;
  2. 当执行Integer b = 200;时,Integer.valueOf(200)会创建新的Integer对象,而非复用缓存;
  3. ==比较的是对象的内存地址,因此:
  • Integer a = 127; Integer b = 127; -> a == b -> true(复用缓存,地址相同);
  • Integer a = 128; Integer b = 128; -> a == b -> false(新建对象,地址不同)。

代码示例

java 复制代码
public class Integer128Test {
    public static void main(String[] args) {
        // 127在缓存范围内,复用对象
        Integer a = 127;
        Integer b = 127;
        System.out.println(a == b); // 输出true
        
        // 128超出缓存范围,创建新对象
        Integer c = 128;
        Integer d = 128;
        System.out.println(c == d); // 输出false
        
        // 正确的比较方式:用equals(比较值)
        System.out.println(c.equals(d)); // 输出true
    }
}

输出:

扩展说明

  • 缓存范围可以通过JVM参数调整上限(但下限固定为-128);

-XX:AutoBoxCacheMax = <size>

  • 不仅Integer,Byte、Boolean(全部缓存)、Short/Long(-128-127缓存)也有类似的缓存机制,Character缓存为0-127。
  • 这种缓存机制能够减少内存消耗,提高性能。

==和equals的区别

核心区别总结

分场景详细解释

1.==使用规则
  • 基本数据类型(如 int、double、char) :直接比较值是否相等
java 复制代码
int a = 10;
int b = 10;
System.out.println(a == b); // true
  • 引用数据类型(如 Object、String、自定义类) :比较对象的内存地址是否相等(即是否为同一个对象)
java 复制代码
String s1 = new String("test");
String s2 = new String("test");
System.out.println(s1 == s2); // false(两个不同对象,地址不同)
2.equals使用规则
  • 默认实现(Object 类) :底层就是用==比较地址
java 复制代码
public boolean equals(Object obj) {
    return (this == obj);
}
  • 重写后(如 String、Integer) :改为比较对象的实际值
java 复制代码
String s1 = new String("test");
String s2 = new String("test");
System.out.println(s1.equals(s2)); // true(比较字符串内容)

Integer i1 = new Integer(100);
Integer i2 = new Integer(100);
System.out.println(i1.equals(i2)); // true(比较数值)
  • 自定义类 :若未重写equals(),则沿用 Object 的地址比较;若需比较对象属性,需手动重写
java 复制代码
class User {
    private String name;
    private int age;
    
    // 重写equals,比较name和age
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age && Objects.equals(name, user.name);
    }
}

总结

  1. 128 陷阱 :核心是IntegerCache缓存池导致-128-127的Integer复用对象,超出范围新建对象,因此比较Integer值时务必用equals()而非==。
  2. == vs equals :==是运算符,基本类型比数值、引用类型比地址;equals()默认比地址,重写后(如 String)比实际值,引用类型比较内容时优先用equals()。
相关推荐
半摆烂日常32 分钟前
手机表单的左滑操作:触摸事件的处理细节
大数据·开发语言·人工智能·智能手机·https·c#
星夜离尘5643 分钟前
MATLAB滑动RMS如何接报警:窗口未满和缺样不能当成正常
开发语言·matlab
SL_staff1 小时前
周报越厚问题越拖?用结构化执行机制让周报回归决策价值
java·spring cloud·开源
开开心心就好1 小时前
白天晚上自动调蓝光,护眼工具亮度可调
服务器·开发语言·算法·pdf·ocr·intellij-idea·idea
张张123y1 小时前
后端第十一课:RAG 落地实战(从 0 到 1 接上私有知识库,并设计一个好用的 RAG)
开发语言·人工智能·python·机器学习·fastapi·rag
梅梅绵绵冰1 小时前
JVM虚拟机
java·开发语言·jvm
golang学习记1 小时前
Python vs Go:2026年到底该怎么选
java·vscode·python·golang·pycharm·goland
Shaoshing1 小时前
消息顺序
java·开发语言
云水初2 小时前
【项目篇】基于LanGraph的自动处理客服邮件的 Agent汇总
开发语言·笔记·python·学习·fastapi·langgraph
茉莉玫瑰花茶2 小时前
GO [ 内存与变量逃逸分析 ]
开发语言·后端·golang