一、核心区别与底层原理
1. == 运算符
本质作用:比较的是内存地址(或者说变量的值)。
对于基本数据类型(byte/short/int/long/float/double/char/boolean):
==比较的是实际数值(因为基本类型变量直接存储值,没有地址概念)。对于引用数据类型(类 / 数组 / 接口等):
==比较的是对象在堆内存中的地址,只有两个引用指向同一个对象时,==才返回true。
2. equals() 方法
本质作用:是
Object类中的方法,默认实现等价于==(比较地址),但可以被重写,用于比较对象的内容 / 属性是否相等。Object类的默认equals()源码:public boolean equals(Object obj) { return (this == obj); // 底层还是用==比较地址 }常用类(如
String、Integer、Date)都重写了equals(),改为比较内容而非地址。
二、代码示例:直观理解
示例 1:基本数据类型 vs 引用数据类型(==)
public class CompareDemo {
public static void main(String[] args) {
// 1. 基本数据类型:== 比较数值
int a = 10;
int b = 10;
System.out.println(a == b); // true(数值相等)
// 2. 引用数据类型:== 比较地址
String s1 = new String("Java");
String s2 = new String("Java");
System.out.println(s1 == s2); // false(两个不同对象,地址不同)
// 特殊:String常量池(新手易踩坑)
String s3 = "Java";
String s4 = "Java";
System.out.println(s3 == s4); // true(常量池复用同一地址)
}
}示例 2:equals() 方法的使用
public class EqualsDemo {
public static void main(String[] args) {
// 1. String类重写了equals():比较内容
String s1 = new String("Java");
String s2 = new String("Java");
System.out.println(s1.equals(s2)); // true(内容相同)
// 2. 自定义类(未重写equals()):等价于==
Person p1 = new Person("张三", 20);
Person p2 = new Person("张三", 20);
System.out.println(p1.equals(p2)); // false(地址不同)
// 3. 自定义类(重写equals()):比较属性
System.out.println(p1.equals(p2)); // 重写后返回true
}
}
// 自定义Person类
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 重写equals():比较name和age是否都相等
@Override
public boolean equals(Object obj) {
// 1. 地址相同,直接返回true
if (this == obj) return true;
// 2. obj为null或类型不同,返回false
if (obj == null || getClass() != obj.getClass()) return false;
// 3. 强转后比较属性
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
}三、关键注意事项
调用
equals()时,避免空指针异常:错误写法:
String s = null; s.equals("Java");(会抛 NullPointerException)正确写法:
"Java".equals(s);(常量非空,安全)重写
equals()时,建议同时重写hashCode():这是 Java 规范要求(如 HashMap 等集合类依赖两者一致性)。
核心原则:
equals()返回 true 的两个对象,hashCode()必须相等;反之不强制。
总结
==:基本类型比数值,引用类型比内存地址,无法被修改 / 重写。equals():默认比地址,可重写为比对象内容(如 String/Integer),自定义类需手动重写才能比较属性。实际开发中,比较对象内容优先用
equals(),比较地址 / 基本类型值用==。