http://hi.baidu.com/crazygit/item/abacfadf4190bd4fdcf9be5c
java回调机制:
软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。
同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;
回 调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;
异步调用:一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。
回调和异步调用的关系非常紧密:使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。
从维基百科上面摘抄定义:(看完本篇文章再来理解这个定义)
在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。
但是在Java里面,无法传递方法指针,所以我们只能使用接口来实现回调。
所谓的回调,就是程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用自己的程序b中的一个方法,于是,他通过a中的接口回调自己b中的方法。下面是例子。
1. 首先定义一个类Caller,按照上面的定义就是程序员A写的程序a,这个类里面保存一个接口引用。
2. 当然需要接口的定义,为了方便程序员B根据我的定义编写程序实现接口。
3. 第三是定义程序员B写的程序b
4. 测试如下
5. 在测试方法中直接使用匿名类,省去第3步。
看完了上面的文章,直接看下面这篇文章:http://kidult.iteye.com/blog/148982
如果我们要测试一个类的方法的执行时间,通常我们会这样做:
大家看到了testTime()方法,就只有"//测试方法"是需要改变的,下面我们来做一个函数实现相同功能但更灵活:
首先定一个回调接口:
然后再写一个工具类:
大家看到,testTime()传入定义callback接口的execute()方法就可以实现回调功能
熟悉MS-Windows和X Windows事件驱动设计模式的开发人员,通常是把一个方法的指针传递给事件源,当某一事件发生时来调用这个方法(也称为“回调”)。Java的面向对象的模型目前不支持方法指针,似乎不能使用这种方便的机制。
例如,假定当某一事件发生时会得到通知,我们可以定义一个interface:
public interface InterestingEvent {
// 这只是一个普通的方法,可以接收参数、也可以返回值
public void interestingEvent();
}
这样我们就有了任何一个实现了这个接口类对象的手柄grip。
当一事件发生时,需要通知实现InterestingEvent 接口的对象,并调用interestingEvent() 方法。
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 接口,而且要把自己的引用传递给事件的通知者。
public class CallMe implements InterestingEvent {
private EventNotifier en;
public CallMe() {
// 新建一个事件通知者对象,并把自己传递给它
en = new EventNotifier(this);
}
// 实现事件发生时,实际处理事件的方法
public void interestingEvent() {
// 这个事件发生了,进行处理
}
}
以上是通过一个非常简单的例子来说明Java中的回调的实现。
interface InterestingEvent {
public void interestingEvent(String event);
}
class CallMe implements InterestingEvent {
private String name;
public CallMe(String name){
this.name = name;
}
public void interestingEvent(String event) {
System.out.println(name + ":[" +event + "] happened");
}
}
class EventNotifier {
private List<CallMe> callMes = new ArrayList<CallMe>();
public void regist(CallMe callMe){
callMes.add(callMe);
}
public void doWork(){
for(CallMe callMe: callMes) {
callMe.interestingEvent("sample event");
}
}
}
public class CallMeTest {
public static void main(String[] args) {
EventNotifier ren = new EventNotifier();
CallMe a = new CallMe("CallMe A");
CallMe b = new CallMe("CallMe B");
// regiest
ren.regist(a);
ren.regist(b);
// test
ren.doWork();
}
}