文章插图
1. 引言
在计算机程序设计中 , 回调函数 , 简称回调(Callback) , 是指通过函数参数传递到其他代码的 , 某一块可执行代码的引用 。这一设计允许了底层代码调用在高层定义的子程序 。以上是维基百科对“回调函数”的定义 。对于回调 , 不同的语言有不同的回调形式 , 例如:
- C、C++ 允许将函数指针作为参数传递;
- JAVAScript、Python 允许将函数名作为参数传递 。
- 反射;
- 直接调用;
- 接口调用;
- Lambda表达式 。
2. 反射Java 的反射机制允许我们获取类的信息 , 其中包括类的方法 。我们将以 Method 类型去获取回调函数 , 然后传递给请求函数 。示例如下:
Request 类中的 send 方法有两个参数 clazz、method , 分别是Class 类型和 Method 类型 , 这里的 method 参数就是待传入的回调函数 , 而为了通过 invoke 方法进行反射调用 , 还需要一个实例 , 所以将回调函数所在的类的 Class 对象作为参数传递进来 , 通过 newInstance 构造一个对象 , 将顺利通过 invoke 反射调用 。
public class Request{public void send(Class clazz, Method method) throws Exception {// 模拟等待响应Thread.sleep(3000);System.out.println("[Request]:收到响应");method.invoke(clazz.newInstance());}}
CallBack 类很简单 , 只有一个 processResponse 方法 , 用于当作回调函数 , 处理响应 。public class CallBack {public void processResponse() {System.out.println("[CallBack]:处理响应");}}
我们在 main 方法中 , 新开了一个线程去发送请求 , 并且把需要的 CallBack.class 和 processResponse 方法传递进去 。public class Main {public static void main(String[] args) throws Exception {Request request = new Request();System.out.println("[Main]:我开个线程去异步发请求");new Thread(() -> {try {request.send(CallBack.class, CallBack.class.getMethod("processResponse"));} catch (Exception e) {e.printStackTrace();}}).start();System.out.println("[Main]:请求发完了 , 我去干点别的");Thread.sleep(100000);}}/** Output:[Main]:我开个线程去异步发请求[Main]:请求发完了 , 我去干点别的[Request]:收到响应[CallBack]:处理响应*/
这种写法需要传递的参数十分繁琐 。下面介绍一种简单的写法 , 直接调用 。3. 直接调用我们来改写下 send 方法的参数 , 改为一个 CallBack 类型参数 。如下:
在 send 方法中我们不使用反射 , 改为直接通过对象来调用方法 。
public class Request{public void send(CallBack callBack) throws Exception {// 模拟等待响应Thread.sleep(3000);System.out.println("[Request]:收到响应");callBack.processResponse();}}
main 函数中 , 我们 new 了一个 CallBack 对象作为参数传递给 send 方法 。public class Main {public static void main(String[] args) throws Exception {Request request = new Request();System.out.println("[Main]:我开个线程去异步发请求");CallBack callBack = new CallBack();new Thread(() -> {try {request.send(callBack);} catch (Exception e) {e.printStackTrace();}}).start();System.out.println("[Main]:请求发完了 , 我去干点别的");Thread.sleep(100000);}}
这种实现方式十分简单 , 但是存在的问题是不符合修改封闭原则 。也就是说当我们想要换一种“处理响应”的方法时 , 将必须去修改 CallBack 类的 processRequest()方法 。而如果将 CallBack 类改为接口 , 我们就可以仅更换 CallBack 的实现了 。下面请看接口调用的写法 。4. 接口调用【Java回调的四种写法:反射+直接调用+接口调用+Lambda表达式】首先将 CallBack 类改为接口 。
public interface CallBack {public void processResponse();}复制代码
再新增一个 CallBack 接口的实现类 CallBackImpl 。public class CallBackImpl implements CallBack {@Overridepublic void processResponse() {System.out.println("[CallBack]:处理响应");}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Linux 提权—突破受限制的shell权限
- 周冬雨出道前的经历 周冬雨毕业于哪一所初中
- 成为高级黑客必须了解的,cors跨域和jsonp劫持漏洞
- 鲶科鱼类大全 世界上最大的鲇鱼
- 辛苦酿就清香 冻顶茶乡南投鹿谷的围城故事
- 茶之艺术,茶与书画艺术的关系
- 10种常见的MySQL错误,你可中招?
- 加钗农场茶工黄凤,茶园是我发家致富的法宝
- ssh免密登录在Linux服务器之间的设置
- Nginx服务器的六种负载均衡策略详解