Android面试-Java 中 == 和 equals 的区别:从内存模型到实战避坑
在 Java 面试和日常开发中,== 和 equals 的区别是一个绕不开的基础问题。很多人能背出“== 比较地址,equals 比较内容”,但真正理解背后的内存模型、重写规则和常见坑点的人并不多。本文从原理出发,结合代码示例,把这个问题讲透。
一、一句话结论
==比较的是“值”本身:对于基本类型比较数值,对于引用类型比较对象的内存地址(引用是否指向同一个对象)。
equals是Object类的方法,默认实现等价于==,但很多类(如String、Integer)重写了它,用于比较对象的“内容”是否相等。
二、== 的本质:比较值或引用地址
== 是 Java 中的关系运算符,它的行为取决于操作数的类型。
2.1 基本数据类型:比较数值
对于 byte、short、int、long、float、double、char、boolean 这八种基本类型,== 直接比较它们的值。
2.2 引用数据类型:比较内存地址
对于对象引用,== 比较的是两个引用是否指向堆内存中的同一个对象。
上面这段代码中,s1 和 s2 分别通过 new 在堆上创建了两个独立对象,虽然内容都是 "hello",但地址不同,所以 == 返回 false。
三、equals 的本质:可被重写的内容比较
equals 定义在 java.lang.Object 中,源码如下:
可以看到,Object 的默认实现就是 ==。也就是说,如果一个类没有重写 equals,那么它的 equals 和 == 效果完全一样。
3.1 String 对 equals 的重写
String 重写了 equals,逐字符比较内容:
注意第一行 if (this == anObject):先比较地址,地址相同直接返回 true,这是一种性能优化。
3.2 包装类对 equals 的重写
Integer、Long 等包装类也重写了 equals,比较的是包装的数值:
四、经典陷阱:Integer 缓存机制
这是面试中出现频率极高的一个坑:
原因在于 Integer 内部维护了一个缓存数组 IntegerCache,默认缓存范围是 -128 到 127。当使用自动装箱(Integer.valueOf(int))时,如果数值在缓存范围内,会直接返回缓存中的同一个对象,因此 == 为 true;超出范围则会 new 一个新对象,== 为 false。
结论:比较包装类的值,永远使用 equals,不要用 ==。
五、String 常量池的影响
字面量 "hello" 会被放入字符串常量池,s1 和 s2 指向同一个常量池对象;而 new String("hello") 会在堆上创建新对象。
六、如何正确重写 equals
自定义类如果需要按内容比较,必须重写 equals,同时强烈建议重写 hashCode。
重写 equals 需要满足五个约定:自反性、对称性、传递性、一致性,以及与 null 比较返回 false。
6.1 为什么必须同时重写 hashCode
Java 规范要求:如果两个对象 equals 返回 true,那么它们的 hashCode 必须相等。 否则在 HashMap、HashSet 等基于哈希的集合中会出现“存进去却取不出来”的问题。
七、对比总结
| 对比项 | == | equals |
|---|---|---|
| 类型 | 运算符 | Object 类的方法 |
| 基本类型 | 比较数值 | 不适用(基本类型无方法) |
| 引用类型 | 比较内存地址 | 默认比较地址,重写后比较内容 |
| 是否可重写 | 否 | 是 |
| 执行效率 | 高 | 相对较低(可能逐字符/逐字段比较) |
| 典型使用场景 | 基本类型比较、判断是否为同一对象、判空 | 字符串、包装类、自定义对象的逻辑相等判断 |
八、实战建议
- 基本类型:直接用
==。 - 字符串:内容比较用
equals,且把常量放在前面,如"abc".equals(str),避免空指针。 - 包装类:一律用
equals,警惕Integer缓存范围。 - 自定义对象:按业务主键重写
equals和hashCode,推荐使用Objects.equals和Objects.hash。 - 枚举:可以直接用
==,因为枚举实例全局唯一。 - 判空:用
== null,不要用equals。
九、小结
== 关注“是不是同一个”,equals 关注“内容是不是一样”。理解这一点,再结合基本类型与引用类型的差异、String 常量池、Integer 缓存以及 equals/hashCode 契约,就能在实际开发中避开绝大多数相关坑点。
使用小程序,查看更多面试题目,随时随地刷题,刷题更方便!


浙公网安备 33010602011771号