【面试题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-127Integer复用对象,超出范围新建对象,因此比较Integer值时务必用equals()而非==
  2. == vs equals==是运算符,基本类型比数值、引用类型比地址;equals()默认比地址,重写后(如 String)比实际值,引用类型比较内容时优先用equals()
相关推荐
花生了什么事o6 小时前
自定义Spring Boot Starter全流程
java·spring boot·后端
似水এ᭄往昔6 小时前
【Qt】--常用控件(显示类控件)
开发语言·qt
PHP实战开发录6 小时前
PHP文件上传成功为什么页面却找不到
开发语言·nginx·php·开发
torpidcat7 小时前
ruoyi-vue-pro 若依芋道 java springboot +mybatis 生日查询相关
java·vue.js·spring boot
AC赳赳老秦7 小时前
文旅市场公开数据分析:基于 OpenClaw 采集景区客流与门票公示数据,生成区域文旅热度监测报告
java·c语言·python·php·symfony·deepseek·openclaw
云小逸7 小时前
C++ 第一阶段:对象、内存与生命周期
开发语言·c++
玖玥拾7 小时前
Lua 基础语法(二)
开发语言·unity·lua
王的宝库7 小时前
GO常用标准库包
开发语言·后端·golang
geovindu8 小时前
python: Face Recognition
开发语言·后端·python·人脸识别
我命由我123458 小时前
Windows 操作系统 - 启用 D 盘虚拟内存
java·运维·服务器·windows·学习·java-ee·运维开发