2.1 什么是回调:
在计算机科学中,回调函数是指一段以参数的形式传递给其它代码的可执行代码。简单地说,函数A的参数是一个函数,在A中执行这个参数函数的形式与过程就是回调。其中作为参数传入函数A的函数就是回调函数。一般在应用开发过程中,我门是负责编写回调函数的。将函数传入其它函数,要求其它类库函数或者系统执行我们的函数。那么为什么我们不能直接调用这个服务呢?同时,如果要是让我们编写函数A我们该如何做呢?为什么我们不能直接在函数中调用作为参数的那个函数呢?
举个例子:我们现在有一个函数,功能是能够识别杯子容量并自动打水的饮水机,而作为回调函数,其功能是拧开一个杯子,并返回其容量。那么我们的两个函数伪代码可以这样写:
//不同的将要作为回调函数的函数 int fun 打开矿泉水瓶(){ 拧开瓶盖; 调整瓶子状态; return 250; } int fun 打开暖壶(){ 打开外盖; 打开木塞; 调整瓶子状态; return 2000; } int fun 打开饮水瓶(){ 打开开关; 按下按钮; 调整瓶子状态; return 500; } //提供打水服务的函数 void fun 智能饮水机(fun f1){ 启动机器识别功能 int volume = f1; //执行回调函数 打开开关; 放水volume毫升; //本函数提供的服务 关闭开关; }
那么为什么我们的回调函数不能直接调用这个服务呢?或者为什么我们不能直接在函数中调用作为参数的那个函数呢?因为可以把函数提供的功能当成一种通用的服务,而请求者(回调函数)确是可能各不相同且未知的,对于未知的请求者我们无法写出针对他的代码,不过只要他遵守一定的规则(如上面的返回一个整型)就可以调用这个服务。
如果还不理解,可以再看看这篇文章:回调函数(callback)是什么? - 码农的荒岛求生的回答 - 知乎
https://www.zhihu.com/question/19801131/answer/1641403537
2.2 如何用Java实现回调
对于回调,主要就是要把函数作为参数传入到另一个函数中,在C/C++中这个很容易用函数指针实现。在Java中,由于面向对象的特性,可以将一个具有特定回调函数的对象传入到方法中,然后在方法中调用这个对象的特定回调函数(方法)。那么如何确保该对象一定拥有这个特定的回调函数呢?我们知道可以用接口提供一组规范来要求实现类具有某些行为,所以,我们可以要求传入的对象的类必须实现了具有回调函数的接口。而在Java中,一个接口类型变量可以指向任何实现了该接口的类的对象,所以我们只需把函数的参数写成接口类型的变量就可以。
之前打水机的例子用java实现为:
//接口 public interface Openable{ int openBottle(); } //一个实现类 public Class Thermos implements Openable{ ... public int openBottle(){ //作为回调函数 do something... return 500; } ... } //提供打水服务的方法 public void draw_water(Openable bottle){ do something... int volume = bottle.openBottle(); //执行回调函数(对象的方法) do something... }