又遇到了回調函數,此次打算寫下來分享一下。javascript
所謂回調函數,或者在面嚮對象語言裏叫回調方法,簡單點講,就是回頭在某個時間(事件發生)被調用的函數。java
再詳細點:就是一個函數A,做爲參數,傳入了另外一個函數B,而後被B在某個時間調用。python
這裏能夠有疑問了,既然是一個函數調用另外一個函數,能夠在函數體裏面調用啊,爲何還要把函數做爲參數傳到另外一個函數裏被調用?況且還有一些語言(好比java)不支持把函數做爲參數。android
對的,確實能夠在函數體裏調用另外一個函數,功能上好像是沒差異的,可是這裏有一個問題,就是你要調用的這個函數被寫死了,也就是說這樣函數B只能調用函數A了,這樣若是在另外一個情景下,有個與A不一樣實現的函數C也須要在B的某個時刻被調用,那怎麼辦。c++
下面繼續說回調函數,在c/c++裏,回調函數可使用函數指針做爲參數被另外一個函數調用;在c#裏,可使用委託,若是是事件方法的話,還有event關鍵字;在python和javascript裏,能夠直接把函數當對象傳參,這些語言都很好實現回調函數(方法),但是, java呢? 先說點題外話,自從學了C#,就不喜歡java了,曾經一度打算之後再也不用java,但是現實並無那麼理想,我如今要作android,因此仍是不能放下java,並且今天遇到這個回調函數的問題,也是從java裏遇到的,我我的以爲,在這個博客裏出現的語言,除了java外,對於回調,均可以既容易,又好理解的實現,可是java,我以爲並非那樣,否則我也不會來寫這篇博客。c#
好了繼續說,關於java中的回調方法的實現。這篇博客的重點就是說java的。 在java中,回調方法是用借用接口來實現的,我在網上找到一句話:app
「把實現某一接口的類所建立的對象的引用,賦值給該接口聲明的接口變量,那麼該接口變量就能夠調用被實現的接口的方法」。ide
很繞哈,簡單解釋下:
有一個接口,接口裏有一個方法(這個方法就是要回調的方法):函數
interface CallBackInterface { void callBackMethod(); }
咱們知道,接口對象不能直接用,由於裏面的方法都沒有實現。因此要找個類實現這個接口。
因此如今加一個類,實現這個接口:this
interface CallBackInterface { void callBackMethod(); } class CallBackClass implements CallBackInterface{ @Override public void callBackMethod() { System.out.println("hello"); } }
好了,最後一步:把實現了接口的類的對象賦值給聲明的接口變量(我給寫進一個方法裏了,而後外面加了個類的殼子):
public class CallBackTest { interface CallBackInterface { void callBackMethod(); } class CallBackClass implements CallBackInterface { @Override public void callBackMethod() { System.out.println("hello"); } } public void showCallBack() { CallBackInterface itfs = new CallBackClass(); itfs.callBackMethod(); } }
如今能夠調用試試看了:
public class Test { public static void main(String[] args) { new CallBackTest().showCallBack(); } }
沒意外的話,會成功輸出hello,反正我這邊是的.
例子看完了,因此說我作了什麼呢? 再詳細點說,咱們有一個要在某一個方法裏被調用的方法(這個方法就是回調方法), 前面咱們也說了,最好不要直接把想要回調方法作的事直接寫在調用方法裏, 又由於java裏無法把方法當作參數傳遞,因此咱們只好把這個回調方法放在了接口裏(爲何不是類?不是抽象類?而是接口?你能夠本身去找下抽象類與接口的異同,本身解決這個問題)。有接口的話,就要被類實現,而後,只要是給接口的對象賦予實現類的對象,這個接口的對象就能夠調用那個方法了。理解這裏的話,有一個重點,就是多態, 這裏用到的多態知識就是,接口的對象能夠順利被子類賦值,而且調用子類的重寫方法(類也有相似的概念)。
再多說一點,這裏任何實現了CallbackInterface接口的類,均可以像下面這樣放在new後面(就是賦值):
public class CallBackTest { interface CallBackInterface { void callBackMethod(); } class CallBackClass implements CallBackInterface { @Override public void callBackMethod() { System.out.println("hello"); } } class Controller { private CallBackInterface cbitf; // 這個boolean只是爲了模擬有事件,沒啥實用價值 public boolean somethingHappend; // 這裏確實能夠直接把CallBackClass作參數,並且省掉接口的定義 // 可是這樣作的話,就像是回調函數直接寫在了調用函數裏同樣 // 不明白的話就好好理解下"約定"和"調用者無論回調函數是怎麼實現的"吧 public Controller(CallBackInterface itfs) { somethingHappend = true; this.cbitf = itfs; } public void doSomething() { if(somethingHappend) { cbitf.callBackMethod(); } } } public void showCallBack() { CallBackClass cbc = new CallBackClass(); Controller ctrlr = new Controller(cbc); ctrlr.doSomething(); // 其實上面也能夠這樣寫在一行裏 // new Controller(new CallBackClass()).doSomething(); } }
最後多說一點,其實這種應用在android裏會常常遇到,我就是在學android的時候遇到的。