Java回调函数

该文章已生成可运行项目,

一、什么是回调(Callback)?


回调是一种常见的编程模式,允许一个函数在特定事件或任务完成后,调用另一个预先定义的函数。在Java中,由于不支持函数指针,通常通过接口或Lambda表达式实现回调。

核心思想:

定义回调接口:声明回调方法。

传递接口实现:将回调逻辑传递给调用方。

触发回调:在特定时机(如任务完成、事件发生)调用回调方法。

二、回调的典型使用场景

事件处理:如按钮点击、数据加载完成。

异步任务:如网络请求完成后通知主线程。

自定义逻辑注入:如排序算法中自定义比较规则。

框架扩展点:如Spring的ApplicationListener。

三,代码实现

基础:
// 1. 定义回调接口
interface OrderCallback {
    void onOrderCompleted(String orderId, boolean isSuccess);
}

// 2. 业务类
class OrderService {
    public void processOrder(String orderId, OrderCallback callback) {
        System.out.println("处理订单: " + orderId);
        // 模拟订单处理逻辑
        boolean isSuccess = Math.random() > 0.5;
        // 触发回调
        callback.onOrderCompleted(orderId, isSuccess);
    }
}

// 3. 客户端调用
public class CallbackDemo {
    public static void main(String[] args) {
        OrderService orderService = new OrderService();
        orderService.processOrder("ORDER_123", new OrderCallback() {
            @Override
            public void onOrderCompleted(String orderId, boolean isSuccess) {
                System.out.println("订单 " + orderId + " 处理结果: " + (isSuccess ? "成功" : "失败"));
            }
        });
    }
}

讲解:

这段代码就像你点外卖的整个过程,我来用最简单的话解释清楚:首先,你(客户端)在手机上下单后,商家(OrderService)开始做饭,但做饭需要时间,你不能一直盯着手机等。于是你告诉商家:“做好后打电话告诉我结果”(这就是​回调接口​​ )。商家做好饭后,不管是成功做好了还是失败没材料了,都会按照你留的电话打给你说“订单号XXX,成功/失败了”(这就是调用 onOrderCompleted 方法通知结果)。而你在下单时写的那个匿名类,就相当于把电话号码和接到电话后要做的动作(比如打印结果)一次性告诉商家,这样商家处理完订单就能自动通知你,你不需要干等着,这就是​​回调机制​​——事情办完了自动通知你结果,整个过程像自动化的电话回复。

进阶:
// 1. 定义回调接口
interface DownloadCallback {
    void onDownloadSuccess(String filePath);
    void onDownloadFailure(String error);
}

// 2. 异步任务类
class DownloadTask {
    public void downloadFile(String url, DownloadCallback callback) {
        new Thread(() -> {
            try {
                System.out.println("开始下载: " + url);
                Thread.sleep(2000); // 模拟下载耗时
                // 模拟下载成功
                String filePath = "/downloads/" + url.substring(url.lastIndexOf('/') + 1;
                callback.onDownloadSuccess(filePath);
            } catch (InterruptedException e) {
                callback.onDownloadFailure("下载中断");
            } catch (Exception e) {
                callback.onDownloadFailure("网络错误");
            }
        }).start();
    }
}

// 3. 客户端调用(模拟UI更新)
public class AsyncCallbackDemo {
    public static void main(String[] args) {
        DownloadTask downloadTask = new DownloadTask();
        downloadTask.downloadFile("https://example.com/file.zip", new DownloadCallback() {
            @Override
            public void onDownloadSuccess(String filePath) {
                System.out.println("下载完成,文件路径: " + filePath);
                // 实际场景中可更新UI
            }

            @Override
            public void onDownloadFailure(String error) {
                System.err.println("下载失败: " + error);
            }
        });
        System.out.println("主线程继续执行其他任务...");
    }
}

讲解:

想象你让室友帮你下电影。你不会傻站在他电脑前干等,而是说"下好了把存哪儿微信发我,出问题就吱一声"——这就是​​回调接口​​的精髓,提前约定好通知方式。

代码里的DownloadTask就像你室友,它接到任务后直接开个新线程干活(就像你室友搬出自己笔记本电脑开始下载),这时候你完全不用干瞪眼等着,该刷剧刷剧该打游戏打游戏(主线程继续输出"我先去忙别的")。

如果2分钟后顺利下完,你手机就会叮咚一声收到他发的文件路径(触发onDownloadSuccess);要是中途突然断网,你立马就能收到他的吐槽"淦!没网了下个锤子"(触发onDownloadFailure)。

整个过程就像现实托人办事:你把任务交代清楚(定义回调方法),对方领命而去(开新线程),你该干嘛干嘛(主线程不阻塞)。等对方搞定/搞砸了,自然会按约定方式给你反馈。这种​​异步回调​​就像当甩手掌柜,把耗时的脏活累活扔到后台,结果出来自动提醒你善后,效率直接拉满!

优点

解耦性强​​

​​场景​​:A 模块调用 B 模块完成任务,B 完成后通知 A,但 A 不需要知道 B 的具体实现。

支持异步处理​​

​​场景​​:耗时操作(如网络请求、文件下载)不阻塞主线程。

​​灵活扩展​​


​​场景​​:同一接口可定义多种回调行为。

缺点

回调地狱

多层嵌套回调导致代码难以阅读和维护。

例如:

login(user, new LoginCallback() {
    @Override
    public void onSuccess() {
        getProfile(new ProfileCallback() {
            @Override
            public void onSuccess(Profile profile) {
                downloadAvatar(profile.getUrl(), new DownloadCallback() {
                    @Override
                    public void onSuccess(String path) {
                        System.out.println("最终成功!");
                    }
                });
            }
        });
    }
});

​​错误处理复杂​​


​​场景​​:每个回调需单独处理异常,代码冗余。

可读性差

代码分散

优化:

回调是小规模异步任务的利器,但面对复杂逻辑时,优先考虑 ​​CompletableFuture​​ 或 ​​响应式编程框架​

总结:

​场景​​用回调​​用替代方案​
简单异步通知 直接易用过度设计
多步骤异步任务 回调地狱 CompletableFuture
需要统一错误处理 冗余代码 异常传播链
UI 事件监听 匿名类或 Lambda 无需替代
本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值