|
|
@@ -954,7 +954,175 @@ public interface SubInterface extends InterfaceA, InterfaceB {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 八、随堂练习要点
|
|
|
+## 八、接口的 JDK 版本演进(Default / Static / Private 方法)
|
|
|
+
|
|
|
+### 1. 不同版本 JDK 的接口组成
|
|
|
+
|
|
|
+**文件**:`Demo06.java`
|
|
|
+
|
|
|
+传统接口中的方法都是 `public abstract` 抽象方法(没有方法体)。从 JDK8 开始,接口的组成逐渐丰富:
|
|
|
+
|
|
|
+| JDK 版本 | 新增特性 | 说明 |
|
|
|
+|---------|---------|------|
|
|
|
+| **JDK1.0~7** | 抽象方法 + 常量 | 方法只能是 `public abstract`,变量只能是 `public static final` |
|
|
|
+| **JDK 8** | **默认方法**(default) | 带有方法体,实现类不强制重写(可选重写,重写时去掉 `default`) |
|
|
|
+| **JDK 8** | **静态方法**(static) | 带有方法体,通过 **接口名** 直接调用 |
|
|
|
+| **JDK 9** | **私有方法**(private) | 带有方法体,用于抽取多个默认方法/静态方法中的公共代码 |
|
|
|
+
|
|
|
+```java
|
|
|
+// 不同版本 JDK 接口的组成
|
|
|
+public interface 接口名 {
|
|
|
+ // JDK1.0~7:抽象方法 + 常量
|
|
|
+ public static final String NAME = "常量";
|
|
|
+ public abstract void abstractMethod();
|
|
|
+
|
|
|
+ // JDK8:默认方法(带方法体,不强制重写)
|
|
|
+ public default void defaultMethod() {
|
|
|
+ // 方法体...
|
|
|
+ }
|
|
|
+
|
|
|
+ // JDK8:静态方法(带方法体,通过接口名调用)
|
|
|
+ public static void staticMethod() {
|
|
|
+ // 方法体...
|
|
|
+ }
|
|
|
+
|
|
|
+ // JDK9:私有方法(带方法体,抽取公共代码)
|
|
|
+ private void privateMethod() {
|
|
|
+ // 方法体...
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 默认方法(default method)——JDK 8
|
|
|
+
|
|
|
+**文件**:`MyDefaultInterface.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public interface MyDefaultInterface {
|
|
|
+
|
|
|
+ // 默认方法——带有方法体,不强制实现类重写
|
|
|
+ default void method() {
|
|
|
+ this.privateMethod();
|
|
|
+ System.out.println("我是接口的默认方法......");
|
|
|
+ }
|
|
|
+
|
|
|
+ default void method02() {
|
|
|
+ this.privateMethod();
|
|
|
+ System.out.println("我是接口的默认方法......");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 抽象方法——实现类必须重写
|
|
|
+ void add(int a, int b);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**默认方法的特点**:
|
|
|
+
|
|
|
+| 特性 | 说明 |
|
|
|
+|------|------|
|
|
|
+| 关键字 | `default`(**不能省略**,`public` 可以省略) |
|
|
|
+| 方法体 | 可以有方法体(不再是纯抽象) |
|
|
|
+| 是否强制重写 | **不强制**,实现类可以选择重写或不重写 |
|
|
|
+| 重写时的注意点 | 重写时 **去掉 `default` 关键字** |
|
|
|
+| 多接口冲突 | 多个接口中存在相同签名的默认方法时,实现类 **必须重写** 该方法 |
|
|
|
+
|
|
|
+### 3. 私有方法(private method)——JDK 9
|
|
|
+
|
|
|
+**文件**:`MyDefaultInterface.java`、`Demo06.java`
|
|
|
+
|
|
|
+**引入原因**:JDK8 允许接口定义带方法体的默认方法和静态方法后,可能出现多个默认方法/静态方法中包含 **相同代码** 的情况。需要把这段代码抽取成共性方法,但又不想被外部使用,所以 JDK9 增加了私有方法。
|
|
|
+
|
|
|
+```java
|
|
|
+public interface MyDefaultInterface {
|
|
|
+
|
|
|
+ // 多个默认方法调用私有方法,避免代码重复
|
|
|
+ default void method() {
|
|
|
+ this.privateMethod(); // 调用私有方法
|
|
|
+ System.out.println("我是接口的默认方法......");
|
|
|
+ }
|
|
|
+
|
|
|
+ default void method02() {
|
|
|
+ this.privateMethod(); // 调用私有方法
|
|
|
+ System.out.println("我是接口的默认方法......");
|
|
|
+ }
|
|
|
+
|
|
|
+ // JDK9 私有方法——抽取多个默认方法的公共代码
|
|
|
+ private void privateMethod() {
|
|
|
+ System.out.println("我是属于MyDefaultInterface的我又n行代码...");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**注意事项**:
|
|
|
+- 接口的 **默认方法** 可以调用接口的 **私有方法**
|
|
|
+- 接口的 **静态方法** 只能调用接口的 **静态私有方法**
|
|
|
+
|
|
|
+### 4. 静态方法(static method)——JDK 8
|
|
|
+
|
|
|
+**文件**:`MyDefaultInterface.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public interface MyDefaultInterface {
|
|
|
+
|
|
|
+ // 静态方法——直接通过接口名调用
|
|
|
+ static void staticMethod() {
|
|
|
+ System.out.println("我是接口的静态方法");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+调用方式:`接口名.静态方法名()`,例如:
|
|
|
+```java
|
|
|
+MyDefaultInterface.staticMethod();
|
|
|
+```
|
|
|
+
|
|
|
+### 5. 实现类与测试
|
|
|
+
|
|
|
+**文件**:`MyDefaultInterfaceImpl.java`、`Test05.java`
|
|
|
+
|
|
|
+```java
|
|
|
+// 实现类——只需要重写抽象方法,默认方法可以不用重写
|
|
|
+public class MyDefaultInterfaceImpl implements MyDefaultInterface {
|
|
|
+ @Override
|
|
|
+ public void add(int a, int b) {
|
|
|
+ System.out.println(a + b);
|
|
|
+ }
|
|
|
+ // method() 和 method02() 是默认方法,不强制重写
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+public class Test05 {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ MyDefaultInterfaceImpl mdii = new MyDefaultInterfaceImpl();
|
|
|
+ mdii.add(1, 2); // 调用实现类重写后的抽象方法 → 输出:3
|
|
|
+ mdii.method(); // 调用接口的默认方法 → 输出:我是属于... + 我是接口的默认方法......
|
|
|
+ MyDefaultInterface.staticMethod(); // 通过接口名直接调用静态方法 → 输出:我是接口的静态方法
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**预期输出**:
|
|
|
+```
|
|
|
+3
|
|
|
+我是属于MyDefaultInterface的我又n行代码...
|
|
|
+我是接口的默认方法......
|
|
|
+我是接口的静态方法
|
|
|
+```
|
|
|
+
|
|
|
+### 6. 接口成员完整总结
|
|
|
+
|
|
|
+| 成员类型 | 修饰符 | JDK 版本 | 是否有方法体 | 实现类是否必须重写 | 调用方式 |
|
|
|
+|---------|--------|---------|------------|-----------------|---------|
|
|
|
+| **常量** | `public static final` | 所有版本 | — | — | `接口名.常量名` |
|
|
|
+| **抽象方法** | `public abstract` | 所有版本 | ❌ 无 | ✅ 必须 | 对象调用 |
|
|
|
+| **默认方法** | `default` | JDK 8+ | ✅ 有 | ❌ 可选(冲突时强制) | 对象调用 |
|
|
|
+| **静态方法** | `static` | JDK 8+ | ✅ 有 | — | `接口名.方法名()` |
|
|
|
+| **私有方法** | `private` | JDK 9+ | ✅ 有 | — | 接口内部调用 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 九、随堂练习要点
|
|
|
|
|
|
**练习目标**:理解抽象类、接口、代码块的基本使用
|
|
|
|
|
|
@@ -964,7 +1132,7 @@ public interface SubInterface extends InterfaceA, InterfaceB {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 九、面试常见问题
|
|
|
+## 十、面试常见问题
|
|
|
|
|
|
**Q1:抽象类能不能被实例化?**
|
|
|
> 不能。抽象类不能直接 `new` 创建对象。
|
|
|
@@ -1011,12 +1179,22 @@ public interface SubInterface extends InterfaceA, InterfaceB {
|
|
|
**Q15:接口为什么不能实例化?接口有构造方法吗?**
|
|
|
> 接口没有构造方法,因此不能实例化(不能创建对象)。接口是一种规范标准,需要通过实现类来提供具体的功能实现。
|
|
|
|
|
|
+**Q16:JDK 8 在接口中新增了哪些特性?**
|
|
|
+> JDK 8 新增了 **默认方法(default)** 和 **静态方法(static)**,它们都可以带有方法体。默认方法通过对象调用,静态方法通过接口名直接调用。
|
|
|
+
|
|
|
+**Q17:接口的默认方法和抽象方法有什么区别?**
|
|
|
+> ① 默认方法有方法体,抽象方法没有;② 默认方法用 `default` 修饰,抽象方法用 `abstract` 修饰;③ 默认方法不强制实现类重写,抽象方法必须重写;④ 重写默认方法时要去掉 `default` 关键字。
|
|
|
+
|
|
|
+**Q18:JDK 9 为什么要在接口中增加私有方法?**
|
|
|
+> JDK 8 允许接口中有带方法体的默认方法和静态方法后,可能出现多个默认方法或静态方法包含相同代码的情况。JDK 9 的私有方法就是为了抽取这些公共代码,避免重复,同时又不对外暴露。
|
|
|
+
|
|
|
---
|
|
|
|
|
|
-## 十、拓展阅读
|
|
|
+## 十一、拓展阅读
|
|
|
|
|
|
- [Java 抽象类(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html)
|
|
|
- [Java 接口(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html)
|
|
|
+- [Java 接口的默认方法(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/IandI/defaultMethods.html)
|
|
|
- [Java 代码块初始化(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html)
|
|
|
- 抽象类 vs 接口(Interface)的区别对比
|
|
|
- 模板方法设计模式(Template Method Pattern)—— 抽象类的经典应用场景
|