Java 回调函数详解html
前言:java
C语言中回调函数解释:程序员
回调函数(Callback Function)是怎样一种函数呢?
函数是用来被调用的,咱们调用函数的方法有两种:ajax
直接调用:在函数A的函数体里经过书写函数B的函数名来调用之,使内存中对应函数B的代码得以执行。这里,A称为“主叫函数”(Caller),B称为“被叫函数”(Callee)。算法
间接调用:在函数A的函数体里并不出现函数B的函数名,而是使用指向函数B的函数指针p来使内存中属于函数B的代码片段得以执行——听起来很酷,是吧。spring
比起直接调用来,间接调用的确麻烦,那为何还要使用间接调用呢?缘由很简单——直接调用把函数名都写进函数体了,通过编译器那么一编译,板上钉钉,A注定调用的是B了,这样的程序只能按照程序员事先设计好的流程执行下去,太呆板了。此时,间接调用的巨大灵活性就显现出来了。想想,若是p是函数A的一个参数(参数是变量,是变量就能够变吗!),那么程序的最终用户彻底能够经过操做来改变p的指向——这样,A在经过p调用函数的时候就有机会调用到不一样的函数,这样程序的实用性和扩展性就强多了。编程
在WINDOWS中,程序员想让系统DLL调用本身编写的一个方法,因而利用DLL当中回调函数(CALLBACK)的接口来编写程序,使它调用,这个就称为回调。在调用接口时,须要严格的按照定义的参数和方法调用,而且须要处理函数的异步,不然会致使程序的崩溃。这样的解释彷佛仍是比较难懂,这里举个简单的例子,程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用本身的程序b中的一个方法,因而,他经过a中的接口回调本身b中的方法。目的达到。在C/C++中,要用回调函数,被掉函数须要告诉调用者本身的指针地址,但在JAVA中没有指针,怎么办?咱们能够经过接口(interface)来实现定义回调函数。服务器
正常状况下开发人员使用已经定义好的API,这个过程叫Call。可是有时这样不能知足需求,就须要程序员注册本身的程序,而后让事先定义好多API在合适的时候调用注册的方法,这叫CallBack。数据结构
“一般你们说的回调函数通常就是按照别人(李四)的定好的接口规范写,等待别人(张三)调用的函数,在C语言中,回调函数一般经过函数指针来传递;在Java中,一般就是编写另一个类或类库的人(李四)规定一个接口,而后你(张三)来实现这个接口,而后把这个实现类的一个对象做为参数传给别人的程序,别人的程序必要时就会经过那个接口来调用你编写的函数。”架构
使用技巧:定一个接口,在接口中声明咱们想调用的方法。
在另外一个方法中注册刚定义的回调接口
第一步:定义回调接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package
com.callback;
/**
*
@since 2012-02-02
*
@desc 定义回调接口
*/
public
interface
CallBackInterface
{
public
void
doSome();
public
void
exectueMethod();
}
|
第二步:李四编写的程序
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
|
package
com.callback;
/**
*
@since 2012-02-02
*
@desc 李四
*/
public
class
MethodB
{
public
double
getTime(CallBackInterface
callBack) {
long
start
= System.currentTimeMillis();
callBack.exectueMethod();
long
end
= System.currentTimeMillis();
System.out.println("cost
time=" +
(end - start));
return
end
- start;
}
}
|
第三步:张三实现李四规定的接口
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
29
30
31
32
33
34
35
36
37
38
39
40
|
package
com.callback;
/**
*
@since 2012-02-02
*
@desc 张三
*/
public
class
MethodA
{
public
static
void
main(String
args[]){
MethodB
b=
new
MethodB();
//返回值d只和MethodB有关,和接口中方法的返回值无关
double
d=b.getTime(
new
CallBackInterface()
{
//张三实现了李四定义的接口
public
void
exectueMethod()
{
new
MethodA().testMethod();
}
@Override
public
void
doSome()
{
}
});
System.out.println(
"d="
+d);
}
public
void
testMethod(){
for
(
int
i=
0
;i<
10000
;i++){
System.out.print(
""
);
}
}
}
|
输出结果:
1
2
|
cost time=
31
d=
31.0
|
理解“回调函数”
所谓回调,就是客户程序CLIENT调用服务程序SERVER中的某个函数SA,而后SERVER又在某个时候反过来调用CLIENT中的某个函数CB,对于CLIENT来讲,这个CB便叫作回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。
通常说来,CLIENT不会本身调用CB,CLIENT提供CB的目的就是让SERVER来调用它,并且是CLIENT不得不提供。因为SERVER并不知道CLIENT提供的CB叫甚名谁,因此SERVER会约定CB的接口规范(函数原型),而后由CLIENT提早经过SERVER的一个函数R告诉SERVER本身将要使用CB函数,这个过程称为回调函数的注册,R称为注册函数。Web SERVERerviCliente以及Java的RMI都用到回调机制,能够访问远程服务器程序。
下面举个通俗的例子:
某天,我打电话向你请教问题,固然是个难题,:),你一时想不出解决方法,我又不能拿着电话在那里傻等,因而咱们约定:等你想出办法后打手机通知我,这样,我就挂掉电话办其它事情去了。过了XX分钟,个人手机响了,你兴高采烈的说问题已经搞定,应该如此这般处理。故事到此结束。这个例子说明了“异步+回调”的编程模式。其中,你后来打手机告诉我结果即是一个“回调”过程;个人手机号码必须在之前告诉你,这即是注册回调函数;个人手机号码应该有效而且手机可以接收到你的呼叫,这是回调函数必须符合接口规范。
经过上面我的感受到回调函数更多的应用就是结合异步。好比:ajax中jServer经过组件和服务器的异步通讯。
什么是回调函数
精妙比喻:回调函数还真有点像您随身带的BP机:告诉别人号码,在它有事情时Call您
回调用于层间协做,上层将本层函数安装在下层,这个函数就是回调,而下层在必定条件下触发回调,例如做为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的处理工做外,还将进行回调,将这个数据交给上层应用层来作进一步处理,这在分层的数据通讯中很广泛。
其实回调和API很是接近,他们的共性都是跨层调用的函数。但区别是API是低层提供给高层的调用,通常这个函数对高层都是已知的;而回调正好相反,他是高层提供给底层的调用,对于低层他是未知的,必须由高层进行安装,这个安装函数其实就是一个低层提供的API,安装后低层不知道这个回调的名字,但它经过一个函数指针来保存这个回调,在须要调用时,只需引用这个函数指针和相关的参数指针。
其实:回调就是该函数写在高层,低层经过一个函数指针保存这个函数,在某个事件的触发下,低层经过该函数指针调用高层那个函数。