==
与 equals()
的区别
在 Java 中,==
和 equals()
都可以用于比较两个值是否相等,但它们适用的类型、比较的内容和结果却有所不同。
一、==
运算符
基本概念:
==
是一个 运算符,用于比较 两个操作数的值是否相等。
使用规则:
数据类型 | 比较内容 |
---|---|
基本数据类型 | 比较的是 值 |
引用数据类型 | 比较的是 内存地址(即对象引用) |
举例说明:
int a = 100;
int b = 100;
System.out.println(a == b); // true,值相等
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false,两个不同的对象,地址不同
String s3 = "hello";
String s4 = "hello";
System.out.println(s3 == s4); // true,字符串常量池中引用的是同一对象
二、equals()
方法
基本概念:
equals()
是 Object 类 提供的方法,用于判断两个对象是否“相等”。- 默认实现(在 Object 类中)是 比较对象的地址(即:
this == obj
)。
方法签名:
public boolean equals(Object obj)
用法与重写:
- 若一个类没有重写
equals()
,则其效果与==
相同; - 若类重写了
equals()
,则可自定义比较逻辑(如按值、按字段比较)。
Object 类中的 equals 源码:
public boolean equals(Object obj) {
return (this == obj); // 默认是地址比较
}
三、实际对比说明
示例代码:
String a = new String("ab"); // 在堆中创建新对象
String b = new String("ab"); // 在堆中创建新对象
String aa = "ab"; // 在字符串常量池中
String bb = "ab"; // 指向常量池中的同一个对象
System.out.println(a == b); // false,堆中两个不同对象
System.out.println(a.equals(b)); // true,String重写了equals,比较内容
System.out.println(aa == bb); // true,常量池中同一对象
System.out.println(a == aa); // false,堆对象 ≠ 常量池对象
System.out.println(42 == 42.0); // true,int 自动转换为 double 后值仍相等
四、String 类中 equals() 的实现
String
类重写了 equals()
方法,使得其比较内容而不是地址:
源码:
public boolean equals(Object anObject) {
// 第一步:检查是否是同一个对象引用(快速路径)
if (this == anObject) {
return true;
}
// 第二步:检查对象是否为String类型(类型检查)
if (anObject instanceof String) {
// 类型安全转型
String anotherString = (String)anObject;
// 第三步:获取当前字符串的长度
int n = value.length;
// 第四步:比较字符串长度(关键优化)
// 如果长度不同则必然不相等
if (n == anotherString.value.length) {
// 第五步:获取字符数组引用
char v1[] = value; // 当前字符串的字符数组
char v2[] = anotherString.value; // 比较字符串的字符数组
int i = 0;
// 第六步:逐个字符比较
// 使用自减计数器的循环(效率优化)
while (n-- != 0) {
// 发现不同字符立即返回false
if (v1[i] != v2[i])
return false;
i++; // 移动到下一个字符
}
// 第七步:所有字符匹配返回true
return true;
}
}
// 第八步:对象不是String类型或长度不同返回false
return false;
}
小结:
- 同引用:立即返回
true
; - 非 String 类型:返回
false
; - 逐字符比较内容:若完全一致,则返回
true
。
五、equals() 的两种使用场景
是否重写 equals() | 行为描述 |
---|---|
没有重写 | 等价于 == ,比较地址 |
重写了 | 比较对象字段内容(如字符串、集合等) |
六、总结对比表
比较项 | == | equals() |
---|---|---|
类型 | 运算符 | 方法(Object类继承) |
适用对象 | 基本类型和引用类型 | 只能用于对象 |
基本类型行为 | 比较值 | 不适用 |
引用类型行为 | 比较内存地址 | 默认比较地址,重写后可自定义内容比较 |
是否可重写 | 不可 | 可由子类重写 |
常用于 | 判断是否同一个对象 | 判断两个对象内容是否相等 |
String默认行为 | 比较引用地址 | 比较字符串值(内容) |
七、使用建议
-
判断值是否相等:使用
equals()
,特别是 String、包装类、集合等。 -
判断是否为同一对象引用:使用
==
。 -
判断 null 前应先反向调用:
if ("abc".equals(s)) // 推荐:避免空指针异常