【面试题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()
相关推荐
SuperEugene2 小时前
Vue3 + Element Plus 表格查询规范:条件管理、分页联动 + 避坑,标准化写法|表单与表格规范篇
开发语言·前端·javascript·vue.js·前端框架
小邓睡不饱耶2 小时前
东方财富网股票数据爬取实战:从接口分析到数据存储
开发语言·爬虫·python·网络爬虫
dapeng28702 小时前
C++与Docker集成开发
开发语言·c++·算法
2501_945423542 小时前
C++中的策略模式实战
开发语言·c++·算法
2301_792308252 小时前
C++与自动驾驶系统
开发语言·c++·算法
hongtianzai2 小时前
Laravel8.x核心特性全解析
java·c语言·开发语言·golang·php
2401_874732532 小时前
模板编译期排序算法
开发语言·c++·算法
逸Y 仙X2 小时前
文章十一:ElasticSearch Dynamic Template详解
java·大数据·数据库·elasticsearch·搜索引擎·全文检索
weixin_421922692 小时前
C++与Node.js集成
开发语言·c++·算法
隔壁小邓2 小时前
IDEA 中同时启动多个微服务
java·微服务·intellij-idea