基本类型用==比较值,引用类型用equals()比较内容;==对引用类型比较地址,仅在判空、单例、枚举等明确需同一实例时使用;equals()需重写才支持自定义类内容比较,推荐常量左置或用objects.equals()防空指针。

直接说重点:基本类型用 ==,引用类型要判断“内容是否一样”就用 equals();只有在确认两个变量指向的是同一个对象(比如单例、缓存对象、内部状态校验)时,才用 == 比较引用。
基本数据类型只能用 ==
byte、short、int、long、float、double、char、boolean 这 8 种类型没有方法,不能调用 equals()。它们的值就存在栈里,== 比的就是数值本身:
- int a = 5; int b = 5; → a == b 是 true
- char c1 = 'x'; char c2 = 'x'; → c1 == c2 是 true
- a.equals(b) 编译直接报错 —— 基本类型没有点号调用方法的能力
引用类型:== 看地址,equals() 看内容(通常)
String、Integer、ArrayList 等都是引用类型。它们的变量存的是堆中对象的地址,== 比的是这两个地址是否相同;而 equals() 默认行为也是比地址(来自 Object),但像 String、LocalDate、BigDecimal 等常用类都重写了它,让它去逐字段比内容。
- String s1 = "abc"; String s2 = "abc"; → s1 == s2 可能为 true(字符串常量池优化)
- String s3 = new String("abc"); String s4 = new String("abc"); → s3 == s4 一定为 false(两个不同对象)
- 但 s3.equals(s4) 是 true —— 因为 String.equals() 比的是字符序列
- 自定义类如 Person p1 = new Person("张三", 25); Person p2 = new Person("张三", 25); → 即使所有字段一样,p1.equals(p2) 默认仍是 false,除非你重写 equals()
什么时候真该用 ==?
不是“少用”,而是“有明确意图时才用”。常见合理场景:
- 检查是否为 null:if (obj == null)(用 obj.equals(null) 会抛 NullPointerException)
- 判断是否是同一实例,比如单例模式:if (instance == getInstance())
- 枚举比较:DayOfWeek.MONDAY == day 安全且高效(枚举值天然单例)
- 性能敏感的内部校验,比如某些缓存 key 的快速判等(先 == 再 equals,即“短路优化”)
用 equals() 的安全习惯
避免空指针,推荐把常量或已知非空对象放左边:
- ✅ "hello".equals(str) —— str 为 null 也不报错,返回 false
- ❌ str.equals("hello") —— str 为 null 时直接崩溃
- Java 7+ 也可用 Objects.equals(a, b),自动处理 null










