当前位置: 首页 > news >正文

java-接口适配器模式 jsk8 接口默认实现

一、接口适配器模式

1-1. 问题背景

有时候,一个接口里可能有很多方法,比如:

public interface Listener {void onStart();void onRun();void onStop();void onError();void onTimeout();// ... 假设有100个方法
}

但是现在类 A 只想用其中 1~2 个方法,如果直接实现接口:

class A implements Listener {@Overridepublic void onStart() {}@Overridepublic void onRun() {}@Overridepublic void onStop() {}@Overridepublic void onError() {}@Overridepublic void onTimeout() {}
}

你会发现:

你必须把所有方法都实现一遍,即使大部分不需要。

非常麻烦。


1-2. 解决办法:接口适配器(Adapter Class)

一个类 来实现接口,并把所有方法写成空实现:——适配器类

public abstract class ListenerAdapter implements Listener {public void onStart() {}public void onRun() {}public void onStop() {}public void onError() {}public void onTimeout() {}
}

然后 A 不再直接实现接口,而是 继承这个适配器类

class A extends ListenerAdapter {@Overridepublic void onRun() {System.out.println("A 自己只关心 onRun");}
}

这样:

  • A 只需要重写自己关心的方法

  • 不用理会其他 99 个方法

  • 简化实现


1-3. 这种模式叫什么?

接口适配器模式(Interface Adapter Pattern)

又叫:

  • 缺省适配器

  • 默认适配器

  • 抽象适配器模式

本质:用一个抽象类“兜底”,替你把多余的方法空实现掉。


1-4. Spring 里也大量使用这种适配器!

比如你写过:Servlet API:

public class MyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) {...}
}

为什么你只写 doGet() 就够了?

因为 HttpServlet 已经帮你把其他方法空实现了 —— 完全就是接口适配器模式

再比如 Spring 的:

场景适配器类用途
Spring 事件监听ApplicationListener + ApplicationListenerMethodAdapter避免每次自己判断类型
MVC 拦截器HandlerInterceptorAdapter(旧版)让你只写 preHandle/afterCompletion
AOP 切点解析MethodInterceptorAdapter避免每种通知方式都要实现很多接口

最后一句总结

接口适配器模式是为了解决“接口方法太多,而实现类只需要部分方法”的问题。
它通过提供一个抽象适配器类,空实现所有方法,子类只重写需要的部分即可。


二、java 8新特性:接口的默认实现


2-1. 以前的接口有什么问题?(Java 8 之前)

Java 8 之前 接口里只能写方法声明,不能写方法实现

public interface A {void test();
}

一个接口一旦被很多类实现,你想给接口里新增一个方法所有实现类都会编译报错,因为它们没实现这个新方法

这让接口拓展非常痛苦,改一个接口,所有实现类都要改。


2-2. Java 8 是怎么解决的?—— default 方法

Java 8 允许接口中写方法实现,只要加 default 关键字

public interface A {default void test() {System.out.println("我是接口里的默认实现");}
}

这样:

  • 实现类 可以不用重写 test()

  • 如果实现类想改,也可以自己重写

这叫 接口默认方法(Default Method)


2-3. 示例代码

定义接口

public interface UserService {// 默认实现default void login() {System.out.println("默认登录逻辑:记录日志 + 输出 登录成功");}
}

实现类

public class UserServiceImpl implements UserService {// 不写 login() 也不会报错
}

使用

public class Test {public static void main(String[] args){UserService userService = new UserServiceImpl();userService.login(); // ✅ 直接用接口里的实现}
}

运行结果:

默认登录逻辑:记录日志 + 输出 登录成功

接口直接给了实现类一个默认行为


2-4. 实现类可以自己重写吗?——可以(覆盖)

public class UserServiceImpl implements UserService {@Overridepublic void login() {System.out.println("自定义登录逻辑");}
}

输出变为:

自定义登录逻辑

2-5. 为什么要有 default 方法?

为了不破坏已有实现类,让接口可以“向后兼容” + “添加新能力”。

比如 Java 8 给 List 接口新增了 forEach() 方法,就是用的 default:

default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}
}

如果没有 default
→ List 的所有实现类(ArrayList, LinkedList, …)都要改
→ 不现实


2-6. 和 abstract 的区别?

关键字出现位置是否有方法体实现类需不需要实现
abstract抽象类或接口❌ 没有方法体✅ 必须重写
default接口✅ 有方法体❌ 可选重写

2-7. 和 static 方法的区别(也出现在 Java 8 接口中)

public interface A {static void tool() { System.out.println("工具方法"); }
}
类型调用方式
default 方法对象.default方法()
static 方法接口名.static方法()

2-8. 两个接口提供同名 default 方法怎么办?

如果一个类实现了两个接口,而这两个接口有同名 default 方法,则必须重写

interface A { default void hello(){ System.out.println("A"); } }
interface B { default void hello(){ System.out.println("B"); } }class C implements A, B {@Overridepublic void hello() {A.super.hello(); // 指定调用哪个}
}

最终一句话总结

Java 8 允许接口通过 default 方法带实现,目的是让接口“可扩展不破坏旧代码”。
实现类可以直接用,也可以选择重写。


三、二者之间的关系

Java 8 的接口默认方法(default)其实就是为了解决“接口适配器模式”里必须写适配器类的问题。


3-1、问题回顾

接口适配器模式要解决的是这个问题:

接口方法太多,类只想实现其中几个方法。

传统解决方式:

接口 → 适配器类(空实现所有方法)→ 你的类继承适配器类

1、Java 8 之前(没有 default 的年代):必须写“接口适配器类”

比如:

public interface Listener {void onStart();void onRun();void onStop();
}public abstract class ListenerAdapter implements Listener {@Override public void onStart() {}@Override public void onRun() {}@Override public void onStop() {}
}public class A extends ListenerAdapter {@Override public void onRun() {System.out.println("只关心 onRun");}
}

你必须创建这个 Adapter 类,来帮你把不关心的方法空实现。


2、Java 8 出现 default 方法之后

接口可以直接写默认实现:

public interface Listener {default void onStart() {}default void onRun() {}default void onStop() {}
}

然后你的类 可以直接实现接口

public class A implements Listener {@Overridepublic void onRun() {System.out.println("只关心 onRun");}
}

不需要再写 Adapter 类了!!!


3、直接对比

时代怎么解决方法太多的问题是否需要写“适配器类”
Java 8 之前写一个抽象适配器类,空实现所有方法✅ 需要
Java 8 之后接口中直接用 default 提供默认实现❌ 不需要

3-2、一句话总结两者关系

Java 8 的接口 default 方法,就是对“接口适配器模式”的语言级支持。
它让你不再需要专门写适配器类。

换句话说:

default 方法 = 把适配器类“搬回接口内部”了。

http://www.dtcms.com/a/560873.html

相关文章:

  • program.cs文件详解
  • 深圳市企业网站seo做东西的网站有那些
  • 京东测开面经整理(日常实习)
  • 大文件上传
  • 做ppt找图片网站推广网发布的信息准确吗
  • Linux内核POSIX文件锁机制深度解析
  • 从“CPU 烧开水“到优雅暂停:Go 里 sync.Cond 的正确打开方式
  • 大模型系列——Excel数据治理新思路:引入智能体实现自动纠错【Python+Agent】
  • Pyppeteer 使用教程
  • React性能优化:useMemo vs useCallback
  • Onsemi展示了垂直GaN-on-GaN半导体
  • 专业机票网站建设禅城区建设局网站
  • Java 日志演进:一文读懂主流框架
  • 第3章 变量与数据类型
  • pyside6 qt 事件循环
  • Secertpad搭建
  • 吞吐量、延迟、内存:深入理解垃圾回收的“三元悖论”
  • List接口和常用方法
  • 计算机一级考试网站怎么做用织梦系统做网站产权
  • Java 数据结构第二十八期:反射、枚举以及 lambda 表达式
  • Linux 磁盘分区与系统监控完全指南
  • 是普通网站地图好还是rss地图好一点网站建设申请费用
  • 使用Graphics2D创建滑块验证码
  • Flutter provide框架内部实现原理刨析
  • 关于rpm,yum,apt
  • 15.6.Bat脚本编写
  • 景德镇网站制作广告法
  • 可以做头像的网站网站区域名是什么
  • 新手记录使用uniapp-x开发鸿蒙应用
  • Linux+Apache+MySQL+PHP 架构下搭建 Discuz 社区论坛