==比较值或地址取决于类型:基本类型比值,引用类型比地址;equals()默认同==,重写后比内容,自定义类需同时重写hashCode()以满足集合要求。

== 比较的是值还是地址,完全看变量类型
基本数据类型(int、char、boolean 等)用 ==,比的就是数值本身:int a = 5; int b = 5; a == b → true。但只要换成引用类型(比如 String、Customer),== 就只认内存地址:哪怕两个 new String("hello") 内容一模一样,== 也返回 false,因为它们是堆里两块不同的内存。
容易踩的坑:
- 误把字符串字面量和
new String()当成一回事:"abc" == new String("abc")是false,但"abc" == "abc"是true(字符串常量池复用) - 对自定义类对象直接用
==判断“内容是否相同”,结果永远是false(除非真指向同一实例)
equals() 默认行为和 String 等类的重写差异
equals() 是 Object 类的方法,原始实现就是 return (this == obj) —— 和 == 完全等价。真正让它“有用”的,是像 String、Integer、Date 这些类主动重写了它,改成逐字符/逐字段比较内容。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 判断字符串内容是否一致,必须用
.equals(),别信== - 调用
equals()前,先确认目标类是否重写了它;没重写的自定义类,equals()和==效果一样 - 永远避免
obj.equals(null),会抛NullPointerException;更安全写法是Objects.equals(a, b)
自定义类想用 equals() 比内容?重写规则不能漏
如果你写了个 Person 类,希望两个 Person 对象在 name 和 age 相同时就判定相等,就必须重写 equals() 方法。但只改 equals() 不够 —— 规范要求:只要重写了 equals(),就必须同步重写 hashCode(),否则放进 HashMap 或 HashSet 会出问题(比如找不到已存入的对象)。
关键点:
-
equals()重写要满足:自反性、对称性、传递性、一致性、对null返回false - 推荐用
Objects.equals(field1, other.field1)处理可能为null的字段,省去判空 - IDE(如 IntelliJ)可一键生成合规的
equals()和hashCode(),别手写
什么时候该用 ==,什么时候非用 equals() 不可
简单说:== 适合判断“是不是同一个东西”,equals() 适合判断“内容是不是一样”。比如检查某个配置对象是否是单例实例,用 ==;检查用户输入的密码和数据库存的密码是否一致,必须用 .equals()。
性能提示:
-
==是 CPU 指令级比较,极快;equals()是方法调用+逻辑判断,慢一点,但该用还得用 - 字符串比较时,
==可作为快速失败检查(先看地址是否相同),再进equals()做内容比对,这是String.equals()源码里的标准写法 - 包装类(如
Integer)有缓存机制:Integer a = 127; Integer b = 127; a == b是true,但a = 128; b = 128就是false—— 别依赖这个,一律用equals()
最易被忽略的一点:equals() 的语义是开发者定义的,不是语言强制的。你重写它,就意味着告诉所有调用方:“从此以后,这两个对象相等的标准,以我的实现为准”。一旦定义了,就要守规矩 —— 特别是 hashCode() 必须配套,否则集合类行为不可预测。










