关于Java 中回调函数的一些理解及与JavaScript的对比

在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。

上面这段是比较官方的定义,我觉得把”回调函数”称呼为”函数传递”、“方法传递”或“代码传递”,更加容易理解一些。

在JavaScript会中更能诠释这一点,也更好理解一些。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//调用者Caller
function caller(callback){
//其他代码逻辑块
console.log('caller:其他代码逻辑块');

callback("hi callback");//调用回调函数

//其他代码逻辑快
console.log('caller:其他代码逻辑块');
}
//被调用者Callee
function callback(param){

console.log('callback:我被caller调用');
console.log('接收到caller调用我时传递的参数'+param);
}
caller(callback);//将callback作为参数传递给caller

----------

//大多数代码中使用回调都是采用下面这种匿名函数的方法(Java中是以匿名类的方式)
caller(function(param){
console.log('callback:我被caller调用');
console.log('接收到caller调用我时传递的参数'+param);
});
</script>

输出:

1
2
3
4
caller:其他代码逻辑块
callback:我被caller调用
接收到caller调用我时传递的参数hi callback
caller:其他代码逻辑块

在Java中相对就变得麻烦了,由于语言的特性,Java要实现回调函数(代码传递)的话要依赖于接口和匿名实现类

1
2
3
4
5
6
7
8
9
10
11
12
//调用者
class Caller{
public void excute(Callback callback){
System.out.println("caller:其他代码逻辑块");
callback.invoke("hi callback");
System.out.println("caller:其他代码逻辑块");
}
}
//被调用者
interface Callback{
void invoke(String param);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class CallbackExample {
public static void main(String[] args) {
Caller caller = new Caller();

//在Java中使用回调函数("方法传递"或"代码传递"可能更加容易理解)的话依赖于函数接口,通常是创建一个函数接口的匿名实现类
caller.excute(new Callback(){
@Override
public void invoke(String param) {
System.out.println("callback:我被caller调用");
System.out.println("接收到caller调用我时传递的参数"+param);
}

});

//上面那个方式等同于这种写法(这样可能更好理解)
Callback callback = new Callback(){
@Override
public void invoke(String param) {
System.out.println("callback:我被caller调用");
System.out.println("接收到caller调用我时传递的参数"+param);
}

};
caller.excute(callback);

});
}
}

输出:

1
2
3
4
caller:其他代码逻辑块
callback:我被caller调用
接收到caller调用我时传递的参数hi callback
caller:其他代码逻辑块

我们可以看到,由于Java是静态语言,实现回调函数(代码传递)的话还是很麻烦的,不过在Java8中加入了Lambda表达式,利用它可以使回调函数(代码传递)变得非常简单和优美。

1
2
3
4
caller.excute((param)->{
System.out.println("callback:我被caller调用");
System.out.println("接收到caller调用我时传递的参数"+param);
});

输出和上面的一样。

在Java中使用回调函数和代理模式有点相似,都是将重复的代码抽象出来,然后由调用者来回调各自不同的逻辑处理代码。

个人总结:回调函数就是把一段代码传递到调用者的方法内,然后执行这段代码。

,