【面试题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()
相关推荐
a程序小傲2 小时前
蚂蚁Java面试被问:注解的工作原理及如何自定义注解
java·开发语言·python·面试
幽络源小助理3 小时前
SpringBoot+Vue摄影师分享社区源码 – Java项目免费下载 | 幽络源
java·vue.js·spring boot
似水এ᭄往昔3 小时前
【C++】--封装红⿊树实现mymap和myset
开发语言·数据结构·c++·算法·stl
0和1的舞者3 小时前
《软件测试分类指南:8 大维度 + 核心要点梳理》
java·软件测试·单元测试·测试·黑盒测试·白盒测试·测试分类
charlie1145141913 小时前
嵌入式现代C++教程:C++98——从C向C++的演化(3)
c语言·开发语言·c++·笔记·学习·嵌入式
TAEHENGV3 小时前
创建目标模块 Cordova 与 OpenHarmony 混合开发实战
android·java·开发语言
程序员zgh3 小时前
C语言 指针用法与区别(指针常量、常量指针、指针函数、函数指针、二级指针)
c语言·开发语言·jvm·c++
是一个Bug3 小时前
如何阅读JDK源码?
java·开发语言
石头dhf3 小时前
大模型配置
开发语言·python