应根据比较目的选择==或equals():==判断引用是否相同,equals()判断内容是否相等;字符串、包装类及自定义对象需重写equals()才能正确比较内容,而单例、null检查、枚举等场景仍应使用==。

直接用 equals() 替代 == 并不总是安全的——关键在于对象是否重写了 equals(),以及你真正想比较的是“是不是同一个对象”还是“内容是否一样”。
字符串比较:必须用 equals(),不能用 ==
字符串是引用类型,== 只认地址,哪怕内容一模一样,只要不是同一个对象实例,结果就是 false。
-
String s1 = "hello"; String s2 = "hello";→s1 == s2是true(字符串常量池优化) -
String s3 = new String("hello"); String s4 = new String("hello");→s3 == s4是false(堆中两个独立对象) - 但
s3.equals(s4)一定是true,因为String类已重写equals()比较字符序列
所以判断字符串内容相等,一律用 .equals();判空时建议用 Objects.equals(str1, str2),它自动处理 null,避免空指针异常。
包装类比较:数值相等优先用 equals()
Integer、Double 等包装类重写了 equals(),比较的是解包后的值,而不是引用。
-
Integer a = 128; Integer b = 128;→a == b是false(超出缓存范围,新建对象) -
a.equals(b)是true(比较的是int值) - 注意:
Integer在-128 ~ 127范围内有缓存,==可能碰巧为true,但这属于实现细节,不可依赖
业务逻辑中只要关心“数值是否相等”,就该用 equals() 或直接用基本类型比较(如 a.intValue() == b.intValue())。
自定义对象:不重写 equals() 就等于没用
如果你写了 Person p1 = new Person("Tom", 25); Person p2 = new Person("Tom", 25);,默认 p1.equals(p2) 仍是 false——因为 Object 的 equals() 就是 ==。
- 必须显式重写
equals()方法,通常配合hashCode()一起重写 - 标准写法包含三步:先判引用相同(
this == obj),再判null和类型,最后逐字段比较 - IDE(如 IntelliJ)可一键生成符合契约的
equals()和hashCode()
否则,放进 HashSet 或作为 HashMap 的 key 时,行为会不符合预期。
特殊场景:== 仍有不可替代的价值
equals() 不是万能替代品;有些时候,== 更准确、更高效、更语义清晰。
- 判断是否为同一实例(比如单例、监听器注册/注销)
- 判断
null:if (obj == null)安全且高效,obj.equals(null)会抛异常 - 枚举比较:
Color.RED == Color.RED是推荐写法,因为枚举常量是单例,==快且线程安全 - 性能敏感路径(如大量循环中的简单判等),
==是 O(1) 地址比对,而equals()可能涉及字段遍历
记住:选 == 还是 equals(),本质是选“身份相等”还是“逻辑相等”,不是语法习惯问题。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











