java中==比较的是内存地址:基本类型比值,引用类型比对象实例;字符串字面量因常量池复用而==为true;equals()需重写以实现逻辑相等,并同步重写hashcode()。

Java里==到底在比什么?
==在Java中永远比较的是「内存地址」——对基本类型,它比值;对引用类型,它比是不是同一个对象实例。
- 基本类型(
int、char、boolean等):直接比较栈上的值,int a = 5; int b = 5; a == b→true - 引用类型(
String、Integer、自定义类等):比较堆中对象的引用地址,new String("a") == new String("a")→false,哪怕内容一模一样 - 字符串字面量例外:
"a" == "a"→true,因为字符串常量池复用了同一地址
为什么equals()不能直接用,还得重写?
默认的Object.equals()方法,底层就是用==实现的——只判断是否为同一对象。所以不重写,它和==行为完全一致。
- 想按「逻辑相等」判断(比如两个
Person对象姓名+年龄相同就算相等),必须重写equals() - 重写时务必同时重写
hashCode(),否则放进HashMap或HashSet会出问题(哈希不一致导致查不到) - 常见漏写:
null检查、类型校验、字段递归比较(如含List字段时没遍历比元素)
String用==还是equals()?看场景
多数时候该用equals();但有少数情况==更快且安全——前提是确认是字符串字面量或已明确intern过。
- 用户输入、JSON解析、数据库查出的
String:一律用str1.equals(str2),避免NullPointerException - 枚举常量、配置项硬编码(如
if (type == "ADMIN")):危险!应改为"ADMIN".equals(type)防空指针 - 确信来源可控且需极致性能(如内部状态机跳转):
==可接受,但得加注释说明依据
Integer等包装类的缓存陷阱
Integer在-128 ~ 127范围会自动缓存,超出后每次new都新建对象——这会让==结果变得不可预测。
立即学习“Java免费学习笔记(深入)”;
-
Integer a = 100; Integer b = 100; a == b→true(命中缓存) -
Integer c = 200; Integer d = 200; c == d→false(各自新建) - 永远别依赖这个行为;需要值比较就用
.equals(),或先intValue()转基本类型再== - 同理适用于
Byte、Short、Character(缓存范围固定),Long和Double无缓存
最易被忽略的点:重写equals()时忘了处理子类继承关系,或者用instanceof导致违反对称性(a.equals(b)为true但b.equals(a)为false)。真要严谨,用getClass() == obj.getClass()更稳妥。










