Java回調函數使用

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中,通常就是編寫另外一個類或類庫的人(李四)規定一個接口,然後你(張三)來實現這個接口,然後把這個實現類的一個對象作爲參數傳給別人的程序,別人的程序必要時就會通過那個接口來調用你編寫的函數。

使用技巧:定一個接口,在接口中聲明我們想調用的方法。

在另一個方法中註冊剛定義的回調接口

第一步:定義回調接口
 
 
  1. ?package com.callback;   
  2.     
  3. /**   
  4.  * @since 2012-02-02   
  5.  * @desc 定義回調接口   
  6.  */ 
  7. public interface CallBackInterface {   
  8.     
  9.     public void doSome();     
  10.         
  11.     public void exectueMethod();   
  12. }   
 
第二步:李四編寫的程序
 
  1. package com.callback;   
  2.     
  3. /**   
  4.  * @since 2012-02-02   
  5.  * @desc 李四   
  6.  */ 
  7. public class MethodB {   
  8.     
  9.     public double getTime(CallBackInterface callBack) {   
  10.         long start = System.currentTimeMillis();   
  11.         callBack.exectueMethod();   
  12.         long end = System.currentTimeMillis();   
  13.         System.out.println("cost time=" + (end - start));   
  14.         return end - start;   
  15.     }   

  第三步:張三實現李四規定的接口

 
  1. package com.callback;   
  2.     
  3. /**   
  4.  * @since 2012-02-02   
  5.  * @desc 張三   
  6.  */ 
  7. public class MethodA {   
  8.     
  9.     public static void main(String args[]){   
  10.         MethodB b=new MethodB();   
  11.         //返回值d只和MethodB有關,和接口中方法的返回值無關   
  12.         double d=b.getTime(new CallBackInterface() {   
  13.                 
  14.             //張三實現了李四定義的接口   
  15.             public void exectueMethod() {   
  16.                 new MethodA().testMethod();   
  17.             }   
  18.                 
  19.             @Override 
  20.             public void doSome() {   
  21.                     
  22.             }   
  23.         });   
  24.         System.out.println("d="+d);   
  25.     }   
  26.         
  27.     public void testMethod(){   
  28.         for(int i=0;i<10000;i++){   
  29.             System.out.print("");   
  30.         }   
  31.     }   

  輸出結果:

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

本文轉自:http://www.cnblogs.com/wangchenyang/archive/2011/08/16/2140744.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章