下面是某位大神對回調的解釋
所謂回調,就是客戶程序client調用服務程序server中的某個函數functionA,然後server又在某個時候反過來調用client中的某個函數functionB,對於client來說,這個functionB便叫做回調函數。例如Win32下的窗口過程函數就是一個典型的回調函數。一般說來,client不會自己調用functionB,client提供functionB的目的就是讓server來調用它,而且是client不得不提供。由於server並不知道client提供的functionB姓甚名誰,所以server會約定functionB的接口規範(函數原型),然後由client提前通過server的一個函數register告訴server自己將要使用functionB函數,這個過程稱爲回調函數的註冊,Register稱爲註冊函數。Web Service以及Java的RMI都用到回調機制,可以訪問遠程服務器程序。
爲了弄明白回調函數的奧妙,首先提出三個問題:
1. 回調函數是什麼東西?
2. 回調函數怎麼開發,怎麼使用?
3. 回調函數的作用,應該在什麼情況下使用?
*******************************************************************************
其實回調就是一種利用函數指針進行函數調用的過程,正面是一些對回調函數的解釋:
1.爲什麼要用回調呢?比如我要寫一個子模塊給你用, 來接收遠程socket發來的命令.當我接收到命令後, 需要調用你的主模塊的函數, 來進行相應的處理.但是我不知道你要用哪個函數來處理這個命令, 我也不知道你的主模塊是什麼.cpp或者.h, 或者說, 我根本不用關心你在主模塊裏怎麼處理它, 也不應該關心用什麼函數處理它...... 怎麼辦?
使用回調!
2.使用回調函數實際上就是在調用某個函數(通常是API函數)時,將自己的一個函數(這個函數爲回調函數)的地址作爲參數傳遞給那個函數。而那個函數在需要的時候,利用傳遞的地址調用回調函數,這時你可以利用這個機會在回調函數中處理消息或完成一定的操作。
3.回調函數,就是由你自己寫的。你需要調用另外一個函數,而這個函數的其中一個參數,就是你的這個回調函數名。這樣,系統在必要的時候,就會調用你寫的回調函數,這樣你就可以在回調函數裏完成你要做的事。
4.回調函數是應用程序提供給Windows系統DLL或其它DLL調用的函數,一般用於截獲消息、獲取系統信息或處理異步事件。應用程序把回調函數的地址指針告訴DLL,而DLL在適當的時候會調用該函數。回調函數必須遵守事先規定好的參數格式和傳遞方式,否則DLL一調用它就會引起程序或系統的崩潰。通常情況下,回調函數採用標準WindowsAPI的調用方式,即__stdcall,當然,DLL編制者可以自己定義調用方式,但客戶程序也必須遵守相同的規定。在__stdcall方式下,函數的參數按從右到左的順序壓入堆棧,除了明確指明是指針或引用外,參數都按值傳遞,函數返回之前自己負責把參數從堆棧中彈出。
總結一下就一句話:回調函數就是函數指針的一種用法。
*********************************************************************
一個很簡單的回調函數:
#include <stdio.h>
void printWelcome(int len)
{
printf("歡迎歡迎 -- %d/n", len);
}
void printGoodbye(int len)
{
printf("送客送客 -- %d/n", len);
}
void callback(int times, void (* print)(int))
{
int i;
for (i = 0; i < times; ++i)
{
print(i);
}
printf("/n我不知道你是迎客還是送客!/n/n");
}
void main(void)
{
callback(10, printWelcome);
callback(10, printGoodbye);
printWelcome(5);
}
上面的代碼沒有被任何系統函數調用,原來回調函數就這麼簡單。
在C/C++中可以通過函數指針來實現回調函數,但是在Java中沒有指針,那Java中如何實現回調函數呢?可以通過接口來實現,下面就是一個實例
package cn.org.lion;
class Caller {
public CallInterface mInterface;
//註冊函數
public void register(CallInterface mInterface)
{
this.mInterface = mInterface;
}
//通過mInterface對象調用(回調)相應的函數
public void callBack_1()
{
this.mInterface.method_1();
}
public void callBack_2(){
this.mInterface.method_2();
}
}
//定義回調函數的接口,該接口中規定了回調函數的聲明格式,可根據定義多個回調方法
interface CallInterface
{
public void method_1();
public void method_2();
}
//實現接口
CallInterface,根據自己的需要實現自己的回調函數,不用管別的類怎麼實現
class MyClass_1 implements CallInterface{
public void method_1(){
System.out.println("111111 MyClass_1's method_1() called");
}
public void method_2(){
System.out.println("222222 MyClass_1's method_2() called");
}
}
//實現接口
CallInterface,根據自己的需要實現自己的回調函數,不用管別的類怎麼實現
class MyClass_2 implements CallInterface{
public void method_1(){
System.out.println("------ MyClass_2's method_1() called");
}
public void method_2(){
System.out.println("****** MyClass_2's method_2() called");
}
}
//測試類
public class TestCallBack{
public static void main(String args[]){
Caller caller = new Caller();
Caller caller1 = new Caller();
caller.register(new MyClass_1());
caller1.register(new MyClass_2());
caller.callBack_1();
caller.callBack_2();
caller1.callBack_1();
caller1.callBack_2();
}
}