Thinking:理解回调

<1>
callback就是回调函数,所谓的回调函数,意指先在系统的某个地方对函数进行注册,让系统知道这个函数的

存在,然后在以后,当某个事件发生时,再调用这个函数对事件进行响应。在awt或swing程序中加入监听器,

其实这个过程就是一个时间回调的过程,具体原理不好说,可以参考一下java的command设计模式,Command模

式就是回调机制的一个面向对象的替代品。
------------------------
<2>
一个类通过一种预定义的协议将自己信息注册完成后,
其他对象通过同一协议获取该类信息后,
可以生成该类型的对象直至调用生成的对象的方法。
调用的过程就是回调吧。

JAVA的CALLBACK通过接口来实现。
例:
1.class A,class B
2.class A实现接口operate
3.class B拥有一个参数为operate接口类型的函数test(operate o)
4.class A运行时调用class B中test函数,以自身传入参数
5.class B已取得A,就可以随时回调A所实现的operate接口中的方法
------------------------
<3>
回调就是在调用一个函数时我们可以传递给该方法一个参数,而这个参数是在调用方定义的一个函数,以便于

在被调用的函数中回过头来调用被作为参数传递的函数。

比如C代码如下:
#include <stdio.h>

void fun2(void){
 printf("asdf");
}

void fun1(void fun2(void)){
 fun2();
}

void fun3(void){
 fun1(fun2);
}

void main(){
 fun3();
}

如果使用java来实现可采用下面的办法:

interface I{void mA();}

public class Test{
  public static void mB(I i){
    i.mA();
  }
  public static void main(String[] args){
    mA(new I(){
      public void mA(){
        System.out.println("asdf");
      }
    });
  }
}

-----------------------
<4>
所谓回调就是主线程新起一个线程后,想让该线程执行完后主线程继续作某事而被新线程调用的一个方法。通

常是主线程的一个静态方法。
具体用法可以参考一下相关多线程编程书。
----------------------
<5>
记得jaxp中响应sax模型事件采用的原理就是callback
比如说解析:
<root>
  <elementA>
   .........
  </elementA>
</root>
当解析元素<root>时,就会触发startelement事件,然后执行你在方法startelement()中所编写的代码.跟着遇上

elementA,然后又调用startelement()
在遇上</elementA>时,调用endelement()方法...遇上</root>时,又去调用
endelement()方法...
如此反复调用特定方法的过程为callback
我记得的就这么多了..

<6>
回调就是你把一个指定的方法交给其他地方调用
参阅设计模式的command模式
简单的代码示范:
定义一个接口:
interface CallbackDemo{
  public void callbackMethod(){
  }
}

调用的类(Demo):
CallBackDemo cd=null;
public void addCallback(CallBackDemo cd){
  this.cd = cd;
}
public void execute(){
  cd.callbackMethod();
}

程序入口:
Demo demo = new Demo();
demo.addCallback(new CallbackDemo(){
  public void callbackMethod(){
    callDetail();
  }
});
...
public void callDetail(){
System.out.println("I'am called!"); 
}
demo.execute();

//你这里调用demo一个方法
//demo类就调用了你这里的callDetail的一个方法
//所以被称为是回调了

回调的目的是把自己的一个方法交到其他对象里面,在C里面是传递方法的地址

 


===========
<7>
用 Java 接口实现回调函数的等价功能 (转载自IBM)

作者:John D. Mitchell
摘要
在 Java 支持方法指针之前,Java 接口不能提供一种实现回调的好方法。如果您习惯于传递在事件驱动编程模

型中调用的函数指针,则您会喜欢本技巧。
熟悉 MS-Windows 和 X Window System 事件驱动编程模型的开发人员,习惯于传递在某种事件发生时调用(即

“回调”)的函数指针。Java 的面向对象模型目前并不支持方法指针,这样似乎就不可能使用这种很好的机制

。但我们并不是一点办法都没有!
Java 的接口支持提供了一种获得回调的等价功能的机制。其技巧就是:定义一个简单接口,并在该接口中声明

我们要调用的方法。

例如,假定我们希望在某个事件发生时得到通知。我们可以定义一个接口:

public interface InterestingEvent
{
// 这仅是一个常规方法。因此如果需要,
// 它可有返回值,也可接收参数。
public void interestingEvent ();
}


这使得我们可以控制实现该接口的类的任何对象。因此,我们不必关心任何外部类型信息。与在将 C++ 代码用

于 Motif 时使用窗口小部件的数据域来容纳对象指针的难以控制的 C 函数相比,这种方法要好得多。

发出事件信号的类必须等待实现了 InterestingEvent 接口的对象,并在适当时候调用 interestingEvent()

方法。

public class EventNotifier
{
private InterestingEvent ie;
private boolean somethingHappened;

public EventNotifier (InterestingEvent event)
{
// 保存事件对象以备后用。
ie = event;

// 还没有要报告的事件。
somethingHappened = false;
}

//...

public void doWork ()
{
// 检查在别处设置的谓词。
if (somethingHappened)
{
// 通过调用接口的这个方法发出事件信号。
ie.interestingEvent ();
}
//...
}

// ...
}


在上例中,我使用 somethingHappened 谓词来跟踪是否应触发事件。在许多情况下,调用此方法足以保证向

interestingEvent() 发出信号。

希望接收事件通知的代码必须实现 InterestingEvent 接口,并将自身引用传递给事件通知程序。

public class CallMe implements InterestingEvent
{
private EventNotifier en;

public CallMe ()
{
// 创建事件通知程序,并将自身引用传递给它。
en = new EventNotifier (this);
}

// 为事件定义实际的处理程序。
public void interestingEvent ()
{
// 噢!必定发生了感兴趣的事件!
// 执行某些操作 ...
}

//...
}


这就是所要做的全部工作。我希望这个简单的 Java 习惯用法会使您更有信心地转向 Java。
================

<8>
最后理解THINKING IN JAVA中的解释,原文:“在callback机制底下,某个对象被赋予一些信息,这些信息允许该对象在稍后某个时间点上调用原先的对象”,比较苦涩一点,呵呵。

回调函数实际上就是在调用某个函数时,将自己的一个函数(这个函数为回调函数)的地址(在JAVA中称为引用)作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数中的函数或成员等。Thimking in Java 第二版中文279--280页的那个程序解释得很清楚。
 

interface Incrementable {
  void increment();
}

// Very simple to just implement the interface:
class Callee1 implements Incrementable {
  private int i = 0;
  public void increment() {
    i++;
    System.out.println(i);
  }
}

class MyIncrement {
  public void increment() {
    System.out.println("Other operation");
  }
  public static void f(MyIncrement mi) {
    mi.increment();
  }
}

// If your class must implement increment() in
// some other way, you must use an inner class:
class Callee2 extends MyIncrement {
  private int i = 0;
  private void incr() {
    i++;
    System.out.println(i);
  }
  private class Closure implements Incrementable {
    public void increment() { incr(); }
  }
  Incrementable getCallbackReference() {
    return new Closure();
  }
}

class Caller {
  private Incrementable callbackReference;
  Caller(Incrementable cbh) {
    callbackReference = cbh;
  }
  void go() {
    callbackReference.increment();
  }
}

public class Callbacks {
  public static void main(String[] args) {
    Callee1 c1 = new Callee1();
    Callee2 c2 = new Callee2();
    MyIncrement.f(c2);
    Caller caller1 = new Caller(c1);
    Caller caller2 =
      new Caller(c2.getCallbackReference());
    caller1.go();
    caller1.go();
    caller2.go();
    caller2.go();
  }
} ///:~

理解一:

在这个函数中Closure就是所谓的回调函数,Caller的构造函数可接收Closuer类型,而正如本例中的Caller caller2 =
      new Caller(c2.getCallbackReference());
      caller2.go();
      就是常用的调用回调函数的手法,caller2实质上调用的是Closuer的increment()方法!
      在JAVA中,一般在事件处理中会经常用到回调函数!

理解二:
不就是两个父类有相同的方法increment(),Callee2要同时继承两个increment()则必须将其中一个放在内部类中继承,通过getCallbackReference()返回内部类对象

理解三:

MyIncrement就像曹操,有void increment() 这个东东,但却不是Incrementable(皇帝)里的那个东东
Callee2是曹丕,继承了他父亲的void increment(),当他想称帝(成为一个Incrementable)的时候,这个假的void increment()不行了,所以,他只能用一个内部类来Incrementable,内部类里的increment()才是真的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值