“回调”这个词通常是跟“异步”联系在一起的。
联系现实生活中的例子。比如你导师交给了你一个任务,然后他就会接着处理他自己的事情去了,直到你完成了任务之后再把结果用邮件告诉他。导师这种布置任务的方式就叫做“异步”。
再看一个"同步“的例子。你的网购快递出了一点问题,想要查一下现在运输到哪里了。于是你打电话给快递公司客服,他让你提供快递单号,你报给他之后便在电话那头等待,直到客服查到快递记录之后告诉你。
总结起来就是,”异步“是调用之后立即返回,”同步“是调用后不返回一直等待。
在”异步“调用中,发起调用的一方(导师),布置任务之后立即就返回了(接着处理自己的事情),所以他并不知道你什么时候把事情做完了,需要你主动”回调“(发邮件给导师)。
所以,“回调”的意思就是说,在异步调用中接受任务的一方完成任务之后,主动通知任务发起方的一种方法。
与”回调“相联系的还有一个叫做”注册“,也即你导师告诉你他的邮箱,这样你才知道任务做完之后应该e-mail给谁。
在查询快递记录的例子中,如果你告诉给客服你的电话,那你也可以立即挂断电话,等待客服查完之后再打电话给你告诉查询的结果。这样也是一个异步调用。
通过上面的解释,读者应该可以理清”异步“、”回调“、”注册“三者之间的关系了。
下面,具体的来考虑在Java中,如何实现回调。
类A,是客户端方,是任务发起方。
类B,是服务器方,是被分配任务方。
A启动一个B的线程,表示A发起一个任务,然后就异步返回了。B处理完之后,调用A的一个方法CallBack(),表示它处理完毕了。
如果没有软件工程的概念,那这种功能也可以这样实现:
//A.java
public class A {
public static void main(String[] args) {
B b = new B();
b.start();
System.out.println("Task assigned");
}
public static void CallBack() {
System.out.println("Task completed, now in CallBack");
}
}
//B.java
public class B extends Thread {
public void run() {
System.out.println("B is executing task...");
A.CallBack();
}
}
运行结果如下:
Task assigned
B is executing task...
Task completed, now in CallBack
可以看到A启动对象b之后,就立即返回了,然后任务被执行,最后返回到A中的CallBack方法。
不过这个方法有一个问题,就是不具有兼容性。我们这里的例子比较简单,都没有入参和出参。实际情况却不是这样,如果A对返回任务的处理需求变了,CallBack需要的参数数量,类型就会改变。这样B中调用A的CallBack的代码就需要进行改动,有可能还很麻烦。不便于后期维护,和进一步的开发。
其实Java中通用回调函数的实现方法是通过接口。
B中定义好接口,接口中定义了回调函数的格式,这样B就知道该如何去调用。A中去实现这个接口,根据自己的实际需要,去处理回调的结果。
代码示例如下:
//A.java
public class A implements MyCallInterface{
public static void main(String args[]) {
B b = new B();
b.registerCallback(new A());
b.start();
System.out.println("task assigned");
}
public void CallBack() {
System.out.println("task completed,now in CallBack");
}
}
//B.java
public class B extends Thread{
public MyCallInterface mc;
public void run() {
System.out.println("B is executing task...");
this.mc.CallBack();
}
public void registerCallback(MyCallInterface mc) {
this.mc = mc;
}
}
//MyCallInterface.java
public interface MyCallInterface {
public void CallBack();
}
运行结果如下:
task assigned
B is executing task...
task completed,now in CallBack
MyCallInterface就是一个接口,它由B去定义,由A去实现。其中一个比较重要的步骤叫注册,即registerCallBack方法,其实就是把A中实现接口的那个类赋值给B。就相当于你导师把他的邮箱地址告诉你。