|
|
@@ -372,18 +372,135 @@ public class Demo03 {
|
|
|
|
|
|
---
|
|
|
|
|
|
+## 四、Object 类(java.lang.Object)—— 所有类的根父类
|
|
|
+
|
|
|
+### 4.1 Object 类概述
|
|
|
+
|
|
|
+`java.lang.Object` 是 Java 中 **所有类的父类**(根父类)。Java 中任何一个类如果没有显式继承其他类,默认都继承自 `Object` 类。
|
|
|
+
|
|
|
+#### 常用方法
|
|
|
+
|
|
|
+| 方法 | 说明 |
|
|
|
+|------|------|
|
|
|
+| `boolean equals(Object obj)` | 比较两个对象是否"相等" |
|
|
|
+| `int hashCode()` | 返回对象的哈希码值 |
|
|
|
+| `String toString()` | 返回对象的字符串表示形式 |
|
|
|
+
|
|
|
+> 📄 来源:`course/api/Demo01.java`
|
|
|
+
|
|
|
+### 4.2 equals() 方法
|
|
|
+
|
|
|
+#### Object 默认实现
|
|
|
+
|
|
|
+在 `Object` 类中,`equals()` 的默认实现使用 `==` 比较,即 **比较两个对象的引用地址**(哈希码值)是否相等。
|
|
|
+
|
|
|
+```java
|
|
|
+// Object 类中 equals 的默认实现
|
|
|
+public boolean equals(Object obj) {
|
|
|
+ return (this == obj);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 重写 equals() 的场景
|
|
|
+
|
|
|
+在实际开发中,我们通常希望 **按照业务规则** 来判断两个对象是否相等。例如,两个 `Person` 对象如果姓名和年龄相同,就应该视为同一个人。
|
|
|
+
|
|
|
+```java
|
|
|
+Person p = new Person("张三", 25);
|
|
|
+Person p1 = new Person("李四", 12);
|
|
|
+System.out.println(p == p1); // false — == 比较的是地址值
|
|
|
+System.out.println(p.equals(p1)); // false — 未重写时与 == 相同
|
|
|
+
|
|
|
+String s1 = new String("张三");
|
|
|
+String s2 = new String("张三");
|
|
|
+System.out.println(s1 == s2); // false — 两个不同的 String 对象
|
|
|
+System.out.println(s1.equals(s2)); // true — String 类已重写 equals
|
|
|
+```
|
|
|
+
|
|
|
+> 📄 来源:`course/api/Demo01.java`
|
|
|
+
|
|
|
+#### 重写 equals() 的规范
|
|
|
+
|
|
|
+```java
|
|
|
+@Override
|
|
|
+public boolean equals(Object o) {
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ Person person = (Person) o;
|
|
|
+ return age == person.age && Objects.equals(name, person.name);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> 📄 来源:`course/api/Person.java`
|
|
|
+
|
|
|
+### 4.3 hashCode() 方法
|
|
|
+
|
|
|
+`hashCode()` 返回对象的 **哈希码值**,在 `Object` 类中默认返回的是该对象在内存中的地址。
|
|
|
+
|
|
|
+#### 重写规则
|
|
|
+
|
|
|
+- **如果两个对象通过 `equals()` 比较相等,那么它们的 `hashCode()` 值必须相等**
|
|
|
+- 重写 `equals()` 时一般都要同时重写 `hashCode()`
|
|
|
+
|
|
|
+```java
|
|
|
+@Override
|
|
|
+public int hashCode() {
|
|
|
+ return Objects.hash(name, age); // 使用 Objects.hash() 工具方法
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> 📄 来源:`course/api/Person.java`
|
|
|
+
|
|
|
+#### Objects 工具类(JDK7+)
|
|
|
+
|
|
|
+`java.util.Objects` 提供了很多安全操作对象的方法:
|
|
|
+
|
|
|
+| 方法 | 说明 |
|
|
|
+|------|------|
|
|
|
+| `Objects.equals(Object a, Object b)` | 安全的 equals 比较(自动处理 null) |
|
|
|
+| `Objects.hash(Object... values)` | 根据多个字段生成哈希码 |
|
|
|
+| `Objects.requireNonNull(Object obj)` | 检查对象是否为 null,为 null 则抛异常 |
|
|
|
+
|
|
|
+```java
|
|
|
+Objects.equals(name, person.name); // 等价于 name != null && name.equals(person.name)
|
|
|
+Objects.hash(name, age); // 根据 name 和 age 生成哈希值
|
|
|
+```
|
|
|
+
|
|
|
+> 📄 来源:`course/api/Person.java`
|
|
|
+
|
|
|
+### 4.4 toString() 方法
|
|
|
+
|
|
|
+`toString()` 将对象转换为字符串表示。Object 默认实现为 `包名.类名 @ 哈希码值的十六进制`。
|
|
|
+
|
|
|
+```java
|
|
|
+// 默认输出如:course.api.Person@3feba861
|
|
|
+
|
|
|
+// 重写后:
|
|
|
+@Override
|
|
|
+public String toString() {
|
|
|
+ return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> 📄 来源:`course/api/Person.java`
|
|
|
+
|
|
|
+### 4.5 IDEA 快速生成
|
|
|
+
|
|
|
+使用 IntelliJ IDEA 开发时,通过 **右键 → Generate → equals() and hashCode() / toString()** 即可快速生成。
|
|
|
+
|
|
|
+> 📄 来源:`course/api/Demo01.java`
|
|
|
+
|
|
|
---
|
|
|
|
|
|
-## 四、课后作业回顾 — StringUtilTest 字符串工具测试
|
|
|
+## 五、课后作业回顾 — StringUtilTest 字符串工具测试
|
|
|
|
|
|
-### 4.1 需求说明
|
|
|
+### 5.1 需求说明
|
|
|
|
|
|
给定有前后空格和重复项的字符串数据 `" 张三, 李四, 王五, 赵六, 张三, 钱七 "`,需要:
|
|
|
1. 去除每个元素的前后空格
|
|
|
2. 去重(去除重复的姓名)
|
|
|
3. 统计每个姓名的出现次数
|
|
|
|
|
|
-### 4.2 相关 API
|
|
|
+### 5.2 相关 API
|
|
|
|
|
|
| 方法 | 说明 |
|
|
|
|------|------|
|
|
|
@@ -391,7 +508,7 @@ public class Demo03 {
|
|
|
| `String.trim()` | 去除字符串前后的空白字符 |
|
|
|
| `Arrays.toString(Object[] a)` | 将数组转换为字符串表示形式 |
|
|
|
|
|
|
-### 4.3 核心算法
|
|
|
+### 5.3 核心算法
|
|
|
|
|
|
#### 三步去重算法
|
|
|
|
|
|
@@ -460,20 +577,20 @@ for (int i = 0; i < newArr.length; i++) {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 五、课后作业回顾 — DataMathTest 日期时间计算
|
|
|
+## 六、课后作业回顾 — DataMathTest 日期时间计算
|
|
|
|
|
|
-### 5.1 需求说明
|
|
|
+### 6.1 需求说明
|
|
|
|
|
|
计算当前日期距离 2026-12-31 还有多少天。
|
|
|
|
|
|
-### 5.2 相关 API
|
|
|
+### 6.2 相关 API
|
|
|
|
|
|
| 方法 | 说明 |
|
|
|
|------|------|
|
|
|
| `LocalDate.of(int year, int month, int dayOfMonth)` | 创建指定日期的 `LocalDate` 对象 |
|
|
|
| `LocalDate.toEpochDay()` | 返回从 1970-01-01 到当前日期的天数 |
|
|
|
|
|
|
-### 5.3 代码实现
|
|
|
+### 6.3 代码实现
|
|
|
|
|
|
```java
|
|
|
LocalDate localDate = LocalDate.of(2026, 7, 27);
|
|
|
@@ -494,9 +611,9 @@ System.out.println("距离 2026-12-31 还有:" + (epochDay - now) + "天");
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 六、随堂练习要点
|
|
|
+## 七、随堂练习要点
|
|
|
|
|
|
-### 6.1 异常处理练习要点
|
|
|
+### 7.1 异常处理练习要点
|
|
|
|
|
|
- 理解 `Throwable` → `Exception` → `RuntimeException` 的继承体系
|
|
|
- 区分编译期异常和运行时异常
|
|
|
@@ -510,7 +627,7 @@ System.out.println("距离 2026-12-31 还有:" + (epochDay - now) + "天");
|
|
|
- 掌握自定义异常的创建步骤(继承 Exception → 无参/有参构造方法)
|
|
|
- 体会异常处理对程序 **鲁棒性(健壮性)** 的提升
|
|
|
|
|
|
-### 6.2 字符串处理综合练习要点
|
|
|
+### 7.2 字符串处理综合练习要点
|
|
|
|
|
|
- 使用 `split(",")` 分割带分隔符的字符串
|
|
|
- 使用 `trim()` 去除字符串前后空格
|
|
|
@@ -518,18 +635,30 @@ System.out.println("距离 2026-12-31 还有:" + (epochDay - now) + "天");
|
|
|
- 掌握元素出现次数的统计算法
|
|
|
- 理解 `equals()` 在字符串比较中的必要性
|
|
|
|
|
|
-### 6.3 日期时间计算练习要点
|
|
|
+### 7.3 日期时间计算练习要点
|
|
|
|
|
|
- 使用 `LocalDate.of()` 创建指定日期
|
|
|
- 使用 `toEpochDay()` 计算两个日期之间的天数差
|
|
|
- 了解其他可选方案:`until()`、`Period.between()`、`ChronoUnit.DAYS.between()`
|
|
|
|
|
|
+### 7.4 Object 类练习要点
|
|
|
+
|
|
|
+- 理解 `Object` 是所有类的根父类
|
|
|
+- 掌握 `equals()` 的重写规范:判断 null → 判断类型 → 比较关键字段
|
|
|
+- 掌握 `hashCode()` 与 `equals()` 的约定:equals 相等则 hashCode 必须相等
|
|
|
+- 掌握 `toString()` 重写,便于输出对象属性
|
|
|
+- 熟悉 `Objects` 工具类的常用方法:`Objects.equals()`、`Objects.hash()`、`Objects.requireNonNull()`
|
|
|
+- 学会使用 IDEA 快捷键生成 `equals()`、`hashCode()`、`toString()`
|
|
|
+
|
|
|
---
|
|
|
|
|
|
-## 七、拓展阅读
|
|
|
+## 八、拓展阅读
|
|
|
|
|
|
1. **Java 异常处理最佳实践** — 何时使用 checked vs unchecked exception,何时自定义异常
|
|
|
2. **try-with-resources** — JDK7+ 自动关闭资源的异常处理方式(`try(Resource r = new Resource()){...}`),是 `finally` 关闭资源方式的进化版,无需手动写 `finally` 块
|
|
|
+3. **`Objects` 工具类源码分析** — 阅读 `java.util.Objects` 的 `equals()`、`hash()`、`requireNonNull()` 源码,理解其安全机制
|
|
|
+4. **`equals()` 与 `hashCode()` 约定详解** — 理解为什么重写 equals 必须重写 hashCode(HashMap/HashSet 等集合类的依赖)
|
|
|
+5. **`toString()` 与日志框架** — 在 SLF4J/Logback 等日志框架中,`toString()` 的正确重写对日志输出非常重要
|
|
|
3. **异常链(Exception Chaining)** — 通过 `initCause()` 或构造方法将底层异常包装为高层异常
|
|
|
4. **`Objects.requireNonNull()`** — 一种优雅避免 NullPointerException 的方式(JDK7+)
|
|
|
5. **`Period` 与 `Duration`** — Java 8 日期时间 API 中更灵活的时间间隔计算
|