Java中实现回调函数

时间:2021-12-14 16:14:49

“回调”这个词通常是跟“异步”联系在一起的。

联系现实生活中的例子。比如你导师交给了你一个任务,然后他就会接着处理他自己的事情去了,直到你完成了任务之后再把结果用邮件告诉他。导师这种布置任务的方式就叫做“异步”。

再看一个"同步“的例子。你的网购快递出了一点问题,想要查一下现在运输到哪里了。于是你打电话给快递公司客服,他让你提供快递单号,你报给他之后便在电话那头等待,直到客服查到快递记录之后告诉你。

总结起来就是,”异步“是调用之后立即返回,”同步“是调用后不返回一直等待。

在”异步“调用中,发起调用的一方(导师),布置任务之后立即就返回了(接着处理自己的事情),所以他并不知道你什么时候把事情做完了,需要你主动”回调“(发邮件给导师)。

所以,“回调”的意思就是说,在异步调用中接受任务的一方完成任务之后,主动通知任务发起方的一种方法。

与”回调“相联系的还有一个叫做”注册“,也即你导师告诉你他的邮箱,这样你才知道任务做完之后应该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。就相当于你导师把他的邮箱地址告诉你。