您的当前位置:首页正文

Java回调函数详解及使用

2023-06-13 来源:易榕旅网
Java回调函数详解及使⽤

Java 回调函数详解前⾔:

C语⾔中回调函数解释:

回调函数(Callback Function)是怎样⼀种函数呢?函数是⽤来被调⽤的,我们调⽤函数的⽅法有两种:

直接调⽤:在函数A的函数体⾥通过书写函数B的函数名来调⽤之,使内存中对应函数B的代码得以执⾏。这⾥,A称为“主叫函数”(Caller),B称为“被叫函数”(Callee)。

间接调⽤:在函数A的函数体⾥并不出现函数B的函数名,⽽是使⽤指向函数B的函数指针p来使内存中属于函数B的代码⽚断得以执⾏——听起来很酷,是吧。

⽐起直接调⽤来,间接调⽤的确⿇烦,那为什么还要使⽤间接调⽤呢?原因很简单——直接调⽤把函数名都写进函数体了,经过编译器那么⼀编译,板上钉钉,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中,通常就是编写另外⼀个类或类库的⼈(李四)规定⼀个接⼝,然后你(张三)来实现这个接⼝,然后把这个实现类的⼀个对象作为参数传给别⼈的程序,别⼈的程序必要时就会通过那个接⼝来调⽤你编写的函数。”

使⽤技巧:定⼀个接⼝,在接⼝中声明我们想调⽤的⽅法。 在另⼀个⽅法中注册刚定义的回调接⼝第⼀步:定义回调接⼝

package com.callback; /** *

@since 2012-02-02 *

@desc 定义回调接⼝ */

public interface CallBackInterface {

public void doSome();

public void exectueMethod();}

第⼆步:李四编写的程序

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; }}

  第三步:张三实现李四规定的接⼝

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(\"\"); } }}

  输出结果:

cost time=31d=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,安装后低层不知道这个回调的名字,但它通过⼀个函数指针来保存这个回调,在需要调⽤时,只需引⽤这个函数指针和相关的参数指针。

其实:回调就是该函数写在⾼层,低层通过⼀个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调⽤⾼层那个函数。

感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!

因篇幅问题不能全部显示,请点此查看更多更全内容