Java回调机制

参考了一下:http://blog.csdn.net/xiaanming/article/details/8703708

http://www.cnblogs.com/wangchenyang/archive/2011/08/16/2140744.html

A类实现了Callback接口C;

A类包含了B类的引用b;

B类包含一个以接口C为参数的方法fb(C c);

A类调用B类的方法fb(C c);

Bfb(C c)中调用A类的方法fa();

 

打电话例子:

小王问小李一个问题:"1+1=?";

小李说"让我想想,有结果了告诉你";

小王说"那我先去干别的事,你有结果了再通知我";

小李想明白了,给小王打电话:"答案是2",问题解决.

 


 

声明一个接口Callback,实现该接口就拥有回调函数;

小王只有实现了该接口,才可以接到小李的通知.

小李有一个函数,该函数有一个参数是Callback接口,这样他有了结果才可以通知需要被通知的人.


代码演示:


/**
 * 这是一个回调接口
 * @author xiaanming
 *
 */
public interface CallBack {
/**
* 这个是小李知道答案时要调用的函数告诉小王,也就是回调函数
* @param result 是答案
*/
public void solve(String result);

}


/**
 * 这个是小王
 * @author xiaanming
 * 实现了一个回调接口CallBack,相当于----->背景一
 */
public class Wang implements CallBack {
/**
* 小李对象的引用
* 相当于----->背景二
*/
private Li li; 


/**
* 小王的构造方法,持有小李的引用
* @param li
*/
public Wang(Li li){
this.li = li;
}

/**
* 小王通过这个方法去问小李的问题
* @param question  就是小王要问的问题,1 + 1 = ?
*/
public void askQuestion(final String question){
//这里用一个线程就是异步,
new Thread(new Runnable() {
@Override
public void run() {
/**
* 小王调用小李中的方法,在这里注册回调接口
* 这就相当于A类调用B的方法C
*/
li.executeMessage(Wang.this, question); 
}
}).start();

//小网问完问题挂掉电话就去干其他的事情了,诳街去了
play();
}


public void play(){
System.out.println("我要逛街去了");
}


/**
* 小李知道答案后调用此方法告诉小王,就是所谓的小王的回调方法
*/
@Override
public void solve(String result) {
System.out.println("小李告诉小王的答案是--->" + result);
}

}


/**
 * 这个就是小李啦
 * @author xiaanming
 *
 */
public class Li {
/**
* 相当于B类有参数为CallBack callBack的f()---->背景三
* @param callBack  
* @param question  小王问的问题
*/
public void executeMessage(CallBack callBack, String question){
System.out.println("小王问的问题--->" + question);

//模拟小李办自己的事情需要很长时间
for(int i=0; i<10000;i++){

}

/**
* 小李办完自己的事情之后想到了答案是2
*/
String result = "答案是2";

/**
* 于是就打电话告诉小王,调用小王中的方法
* 这就相当于B类反过来调用A的方法D
*/
callBack.solve(result); 




}

}


/**
 * 测试类
 * @author xiaanming
 *
 */
public class Test {
public static void main(String[]args){
/**
* new 一个小李
*/
Li li = new Li();


/**
* new 一个小王
*/
Wang wang = new Wang(li);

/**
* 小王问小李问题
*/
wang.askQuestion("1 + 1 = ?");
}
}




C语言中回调函数解释:
回调函数( Callback Function)是怎样一种函数呢?
函数是用来被调用的,我们调用函数的方法有两种:
l         直接调用:在函数 A的函数体里通过书写函数 B的函数名来调用之,使内存中对应函数 B的代码得以执行。这里, A称为“主叫函数”( Caller), B称为“被叫函数”( Callee)。
l         间接调用:在函数 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=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,安装后低层不知道这个回调的名字,但它通过一个函数指针来保存这个回调,在需要调用时,只需引用这个函数指针和相关的参数指针。

其实:回调就是该函数写在高层,低层通过一个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调用高层那个函数。
【参考】
http://blog.csdn.net/sweetwxh/article/details/2067139
http://liutiemeng.blog.51cto.com/120361/18874
http://kidult.iteye.com/blog/148982

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值