第 10 章:Object 类与常用方法
学习目标
- 理解 Object 是所有类的根
- 掌握 equals / hashCode / toString 重写
- 避开 equals 和 hashCode 的常见坑
一、Object 是所有类的祖先
Java 中所有类都直接或间接继承 Object。
java
public class User {
// 没写 extends,但默认继承 Object
}
User u = new User();
System.out.println(u instanceof Object); // true二、equals 默认行为(== 比较地址)
java
public boolean equals(Object obj) {
return (this == obj); // 默认就是 == 比较
}业务上需要"值相等"时,必须重写 equals:
java
public class User {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true; // ① 同一对象,直接返回 true
if (!(o instanceof User)) return false; // ② 类型不对,返回 false
User other = (User) o;
return age == other.age && Objects.equals(name, other.name);
}
}
User u1 = new User("张三", 18);
User u2 = new User("张三", 18);
System.out.println(u1.equals(u2)); // true(值相等)三、equals 和 hashCode 契约
重写 equals 必须同时重写 hashCode,否则用 HashMap / HashSet 会出问题。
java
@Override
public int hashCode() {
return Objects.hash(name, age); // 基于字段生成
}⚠️ 坑 1:两个对象
equals相等 →hashCode必须相等。否则:javaSet<User> set = new HashSet<>(); set.add(new User("张三", 18)); set.contains(new User("张三", 18)); // ❌ false,因为 hashCode 不同找不到
⚠️ 坑 2:字符串比较永远用
equals,不要用==:javaString a = "hi"; String b = new String("hi"); a == b // ❌ false(地址不同) a.equals(b) // ✅ true
四、toString 调试输出
不重写的话,默认打印 类名@哈希码,调试不友好:
java
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
User u = new User("张三", 18);
System.out.println(u); // User{name='张三', age=18}企业建议:每个实体类都重写 toString,调试省事。
五、其他 Object 方法速览
| 方法 | 用途 |
|---|---|
getClass() | 获取运行时类 |
clone() | 浅拷贝(基本类型 OK,引用类型共享) |
wait() / notify() | 线程间协作(并发章节) |
finalize() | GC 前调用(已废弃,别用) |
六、实战:完整 User 类
java
import java.util.Objects;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return age == user.age && Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}七、本章小结
| 要点 | 关键 |
|---|---|
| Object | 所有类的根,默认继承 |
| equals | 默认 == 比较,业务需要"值相等"时必须重写 |
| hashCode | 重写 equals 必须同时重写 hashCode |
| toString | 重写后调试更友好 |
| 字符串比较 | 永远用 equals,不用 == |
动手练习
- 完整实体类:写
Product(id/name/price),重写 equals/hashCode/toString - HashSet 测试:把自定义对象放进
HashSet,验证 equals/hashCode 的作用 - IDE 自动生成:用 IDEA 的
Generate → equals() and hashCode(),看生成的代码