Java接口回调和方法回调的简单实现步骤

 更新时间:2025年03月05日 11:34:08   作者:AutismBtkrsr  
这篇文章主要介绍了Java接口回调和方法回调的相关资料,接口回调是一种设计模式,实现三方解耦,调用者提供接口实现,文中通过代码介绍的非常详细,需要的朋友可以参考下

先来聊接口回调

接口回调

这是一种设计模式,我的理解:

共有三者:调用者,被调用者和接口方法

接口回调的核心在于:调用者只需要实现接口方法,而被调用者只需要在合适的时机反过来调用调用者实现的方法,通过第三者接口方法,实现了双向解耦,调用者不关心被调用者,被调用者不关心调用者如何实现方法的。

回调的核心思想是:

  • 调用者(Caller) 提供一个实现,交给 被调用者(Callee)
  • 被调用者在适当的时机,通过调用该实现来执行相应的逻辑。

"回调"的体现在于:正常都是调用者调用被调用者,而这里是被调用者主动调用调用者

接口回调的实现步骤

1. 定义接口

  • 定义一个接口,其中包含需要被回调的方法。

2. 实现接口

  • 由调用者(Caller)实现这个接口,并提供具体的回调逻辑。

3. 注册接口

  • 将实现接口的对象传递给被调用者(Callee)。

4. 在合适时机回调

  • 被调用者在需要时调用接口中的方法,触发回调逻辑。

举例理解

举一个生活中的例子,比如点外卖

这涉及到三者关系:

  • app用户(调用者)
  • 饿了么app(被调用者)
  • 联系方式(接口方法实现)
  • 【用户】填写了联系方式,比如地址和手机号(实现接口方法)
  • 付款后,【饿了么】开始一系列操作(呼叫商家 ->呼叫骑手等)
  • 无论如何,最终送餐的时候必须知道如何联系【用户】,会调用实现的接口方法
  • 最终送到【用户】手中

这个例子中,想想看,【用户】作为调用者需要关心【饿了么】的一系列流程操作吗?并不需要。【饿了么】需要关心【用户】的联系方式吗?呃。。。。好像的确挺关心的,这个例子翻车了?反正你能理解就行,联系方式就算写错成其他户的地址,【饿了么】的骑手也会照样送过去,这么看也不算关心内容了。

代码案例

写一个简单的代码案例,加深理解

public interface ButtonClickListener {
    void click(); // 回调方法
}

public class Button {
    private ButtonClickListener listener;
    public void setButtonClickListener(ButtonClickListener listener){
        this.listener = listener;
    }
    public void click(){
        if (listener != null){
            listener.click(); // 回调接口方法
        }
    }
}

public class Main implements ButtonClickListener{
    public static void main(String[] args) {
        // 创建被调用者实例
        Button button = new Button();
        // 创建调用者(Main)实例
        Main main = new Main();
        // 注册回调接口
        button.setButtonClickListener(main);
        // 模拟按钮点击
        button.click();
    }
    @Override
    public void click() {
        System.out.println("点击按钮");
    }
}

常见的接口回调

举一个常用的Consumer接口经常出现接口回调现象

关于Consumer接口可以看我另一篇博客:【Java】Java8的4个函数式接口简单教程

Arrays.asList("a", "b", "c")
                .forEach(s -> System.out.println(s));

如上,这行代码其实发生了隐式的接口回调

三者关系:

  • 我(调用者):我调用了集合的forEach()方法,并且我实现了Consumer接口的抽象方法accept()
  • forEach()(被调用者):forEach()方法会自动调用我实现的accept()方法
  • Consumer.accept()(接口方法)

我只需要实现接口方法,forEach()会主动调用我实现的方法,并不关心我到底咋实现的

异步回调

上面说的都是同步回调

  • 回调方法在调用的过程中立即被执行。
  • 示例:按钮点击监听。

异步回调是:

  • 回调方法在调用结束后,异步地被执行(通常是在另一个线程中)。
  • 示例:网络请求完成后通知调用者。
// 异步回调示例(模拟异步任务)
public class AsyncTask {

    // 定义回调接口
    public interface TaskCallback {
        void onTaskComplete(String result);
    }

    // 执行异步任务
    public void execute(TaskCallback callback) {
        new Thread(() -> {
            try {
                Thread.sleep(2000);  // 模拟耗时任务
                String result = "Task Finished!";
                callback.onTaskComplete(result);  // 回调通知任务完成
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

// 调用者代码
public class Main {
    public static void main(String[] args) {
        AsyncTask task = new AsyncTask();
        task.execute(result -> System.out.println("Callback received: " + result));
        System.out.println("Task started...");
    }
}

注意事项

空指针检查

  • 如果没有设置回调接口(即 listener 为 null),直接调用接口方法会抛出 NullPointerException
if (listener != null) {
    listener.onClick();
}

线程安全

  • 在多线程场景下,注意回调接口的线程安全问题,例如异步任务回调需要在主线程中执行。

性能开销

  • 回调接口的调用会带来一定的性能开销,尤其是在高频调用场景中,可能对性能产生影响。

强依赖问题

  • 如果接口实现的方式过于复杂,会导致代码难以维护,因此需要设计合理的接口和实现。

方法回调

差不多,看区别就行

核心记住一句话:将方法作为另一个方法的参数

方法回调:

  • 调用者将某个对象的方法引用直接传递给被调用者,被调用者在适当时机调用这个方法。
  • 不依赖接口,通常通过方法引用或 Lambda 表达式实现。
依赖接口不需要接口,直接传递方法引用需要接口,调用者实现接口并提供逻辑
灵活性不灵活,直接绑定到具体类的方法更灵活,支持不同实现类
解耦程度较低,调用者和被调用者直接关联高度解耦,通过接口隔离调用者与实现者
复杂性简单相对复杂,但更适合扩展场景
  • 方法回调:简单直接调用具体类的方法,适用于调用单一方法的场景。
  • 接口回调:强调解耦,适用于需要灵活多变的回调逻辑场景。

总结就行,区别不大,就是不用实现接口了

三者关系就变成,我调用forEach(),而forEach()调用了我写的Caller.printMessage()方法

总结

到此这篇关于Java接口回调和方法回调的文章就介绍到这了,更多相关Java接口回调和方法回调内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java源码解析之object类

    Java源码解析之object类

    前些天看到别人讨论阅读源码有什么用这个问题,有一句话说的特别好:学习别人实现某个功能的设计思路,来提高自己的编程水平。本文主要介绍了Java源码解析之object类,需要的朋友可以参考。
    2017-10-10
  • 详解Java高阶语法Volatile

    详解Java高阶语法Volatile

    这篇文章主要介绍了Java高阶语法Volatile,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 浅谈Java设计模式系列-装饰器模式

    浅谈Java设计模式系列-装饰器模式

    这篇文章主要介绍了Java设计模式系列-装饰器模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 阿里SpringBoot应用自动化部署实现IDEA版Jenkins

    阿里SpringBoot应用自动化部署实现IDEA版Jenkins

    这篇文章主要为大家介绍了阿里SpringBoot应用自动化部署实现IDEA版Jenkins过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 详解Java中的锁Lock和synchronized

    详解Java中的锁Lock和synchronized

    锁是Java并发编程中最重要的同步机制,Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文将详细介绍Lock和synchronized
    2021-06-06
  • Sentinel 集成 Nacos 实现规则动态推送与持久化的过程

    Sentinel 集成 Nacos 实现规则动态推送与持久化的过程

    本文介绍了如何将Sentinel与Nacos集成,实现流量控制规则的动态推送和持久化存储,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2026-02-02
  • Java Runtime类详解_动力节点Java学院整理

    Java Runtime类详解_动力节点Java学院整理

    Runtime类封装了运行时的环境。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。下面通过本文给大家分享Java Runtime类详解,需要的朋友参考下吧
    2017-04-04
  • OpenFeign实现携带请求头方案详细介绍

    OpenFeign实现携带请求头方案详细介绍

    这篇文章主要介绍了OpenFeign实现携带请求头方案,在通过 ​​OpenFeign​​​进行服务调用的过程中,我们需要将用户的​​user-token​​​、​​lang​​等信息放入请求header中。在分布式系统中,往往一个业务接口内部会发生多次RPC调用
    2022-11-11
  • 最新SpringCloud Stream消息驱动讲解

    最新SpringCloud Stream消息驱动讲解

    SpringCloud Stream 是一个构建消息驱动微服务的框架,通过 SpringCloud Stream 连接消息中间件,以实现消息事件驱动,这篇文章主要介绍了SpringCloud Stream消息驱动,需要的朋友可以参考下
    2022-11-11
  • Java对象比较之equals与hashCode详解

    Java对象比较之equals与hashCode详解

    这篇文章主要介绍了Java对象比较之equals与hashCode详解,equals 方法和 hashCode 方法是 Object 类中的两个基础方法,它们共同协作来判断两个对象是否相等,需要的朋友可以参考下
    2023-12-12

最新评论