更新時間:2020-10-27 17:52:38 來源:動力節(jié)點 瀏覽1540次
回調(diào)(callback)是 Java 中很重要的一個概念,我們在學(xué)習(xí)Spring、Hibernate等計算框架時其實已經(jīng)為Java回調(diào)機制的學(xué)習(xí)埋下了伏筆。我們都知道控制反轉(zhuǎn)(Inversion of Control,IoC),它是一個重要的面向?qū)ο缶幊痰姆▌t,用來削減計算機程序的耦合問題,也是輕量級的 Spring 框架的核心。而控制反轉(zhuǎn)的本質(zhì),就是 Java接口回調(diào)機制。
在某些面向過程(事件驅(qū)動)的編程語言(如 C 語言)中,開發(fā)人員可以通過傳遞函數(shù)指針(function pointer)直接實現(xiàn)回調(diào)機制,回調(diào)的對象可能是一段代碼塊(方法塊)。但 Java 作為一門面向?qū)ο蟮木幊陶Z言,并不支持方法指針(method pointer,在 Java 中,方法的地位等同于 C 中的函數(shù)),所以想實現(xiàn)回調(diào)機制,必須通過「對象(object)」來完成,這似乎妨礙了回調(diào)機制的完成。
回調(diào)的思想是:
類A的a()方法調(diào)用類B的b()方法
類B的b()方法執(zhí)行完畢主動調(diào)用類A的callback()方法
通俗而言: 就是A類中調(diào)用B類中的某個方法C, 然后B類中反過來調(diào)用A類中的方法D, D這個方法就叫回調(diào)方法, 這樣子說你是不是有點暈暈的, 其實我剛開始也是這樣不理解, 看了人家說比較經(jīng)典的回調(diào)方式:
1.class A實現(xiàn)接口CallBack callback——背景1
2.class A中包含一個class B的引用b ——背景2
3.class B有一個參數(shù)為callback的方法f(CallBack callback) ——背景3
4.A的對象a調(diào)用B的方法 f(CallBack callback) ——A類調(diào)用B類的某個方法 C
5.然后b就可以在f(CallBack callback)方法中調(diào)用A的方法 ——B類調(diào)用A類的某個方法D
Java「關(guān)上了一扇門,必然會為你開啟另一扇窗」,而這扇窗就是「接口」。我們通過下面的例子來說明,在 Java 中,調(diào) Java 回調(diào)機制的演示(Caller.java)。
interface CallBack
{
void methodToCallBack( );
}
class CallBackImpl implements CallBack
{
public void methodToCallBack( )
{
System.out.println("I'"ve been called back");
}
}
public class Caller
{
public void register(CallBack callback)
{
callback.methodToCallBack( );
}
public static void main(String[] args)
{
Caller caller = new Caller( );
CallBack callBack = new CallBackImpl( );
caller.register(callBack);
}
}
保存并運行程序,結(jié)果如下圖所示。
代碼詳解
第 01~04 行,聲明了一個接口 CallBack,在這個接口中聲明了一個抽象方法 methodToCallBack( )。
第 05~11 行,用一個名為 CallBackImpl 的類,實現(xiàn)了接口 CallBack。
第 12~24 行,設(shè)計了一個主調(diào)類 Caller,其中第 14~17 行聲明了一個注冊方法 register(),特別需要注意的是,這個方法的參數(shù)是接口對象 CallBack 的引用。
第 20 行,新建了一個 Caller 對象,第 21 行新建了一個 CallBackImpl 的對象,它是接口 CallBack 的具體實現(xiàn)者。
第 22 行,調(diào)用注冊方法 register(),實參就是 CallBackImpl 的對象 callBack,因為 CallBackImpl 實現(xiàn)(某種程度上可以說是繼承)了抽象接口,所以在 register()方法中,callBack 可以調(diào)用 methodToCallBack()方法。
或許,讀者會困惑,為什么不在第 21 行之后這么做。
callback.methodToCallBack()
這樣豈不是更加簡便?的確如此。
但這段代碼不在于如何用最短的代碼實現(xiàn)具體功能,而是為了給我們展示一下,如何在 Java 環(huán)境下實現(xiàn)一個回調(diào)機制。
我們知道,回調(diào)機制的真正意圖,其實是為了實現(xiàn)「控制反轉(zhuǎn)(Inversion of Control)」。通過控制反轉(zhuǎn),對象在被創(chuàng)建的時候(如第 21 行),由一個能夠調(diào)控系統(tǒng)內(nèi)所有對象的外界實體(如第 20 行的 caller),將其所依賴的對象的引用傳遞給功能方法塊(如第 22 行的 callBack,被送入到 register()中)。
我們知道,同一個接口,可以有不同的實現(xiàn)類,從而使得這些不同的實現(xiàn)類,可以定義眾多不同的對象,而這些對象會被按需「注入」功能方法塊 register()。在被調(diào)用前,這些對象永遠處于等待調(diào)用狀態(tài),直到有一天被回調(diào)(callback)。
由上分析可知,控制反轉(zhuǎn)可以用來降低計算機代碼之間的耦合度??偨Y(jié)起來,回調(diào)的核心就是回調(diào)方將本身即this傳遞給調(diào)用方,這樣調(diào)用方就可以在調(diào)用完畢之后告訴回調(diào)方它想要知道的信息?;卣{(diào)是一種思想、是一種機制,至于具體如何實現(xiàn),如何通過代碼將回調(diào)實現(xiàn)得優(yōu)雅、實現(xiàn)得可擴展性比較高,一看開發(fā)者的個人水平,二看開發(fā)者對業(yè)務(wù)的理解程度。觀看本站的Java接口教程,學(xué)習(xí)Java接口的回調(diào)機制,在你的代碼中實現(xiàn)Java接口的回調(diào)吧!