更新時(shí)間:2020-10-27 17:52:38 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1731次
回調(diào)(callback)是 Java 中很重要的一個(gè)概念,我們在學(xué)習(xí)Spring、Hibernate等計(jì)算框架時(shí)其實(shí)已經(jīng)為Java回調(diào)機(jī)制的學(xué)習(xí)埋下了伏筆。我們都知道控制反轉(zhuǎn)(Inversion of Control,IoC),它是一個(gè)重要的面向?qū)ο缶幊痰姆▌t,用來削減計(jì)算機(jī)程序的耦合問題,也是輕量級的 Spring 框架的核心。而控制反轉(zhuǎn)的本質(zhì),就是 Java接口回調(diào)機(jī)制。
在某些面向過程(事件驅(qū)動(dòng))的編程語言(如 C 語言)中,開發(fā)人員可以通過傳遞函數(shù)指針(function pointer)直接實(shí)現(xiàn)回調(diào)機(jī)制,回調(diào)的對象可能是一段代碼塊(方法塊)。但 Java 作為一門面向?qū)ο蟮木幊陶Z言,并不支持方法指針(method pointer,在 Java 中,方法的地位等同于 C 中的函數(shù)),所以想實(shí)現(xiàn)回調(diào)機(jī)制,必須通過「對象(object)」來完成,這似乎妨礙了回調(diào)機(jī)制的完成。
回調(diào)的思想是:
類A的a()方法調(diào)用類B的b()方法
類B的b()方法執(zhí)行完畢主動(dòng)調(diào)用類A的callback()方法
通俗而言: 就是A類中調(diào)用B類中的某個(gè)方法C, 然后B類中反過來調(diào)用A類中的方法D, D這個(gè)方法就叫回調(diào)方法, 這樣子說你是不是有點(diǎn)暈暈的, 其實(shí)我剛開始也是這樣不理解, 看了人家說比較經(jīng)典的回調(diào)方式:
1.class A實(shí)現(xiàn)接口CallBack callback——背景1
2.class A中包含一個(gè)class B的引用b ——背景2
3.class B有一個(gè)參數(shù)為callback的方法f(CallBack callback) ——背景3
4.A的對象a調(diào)用B的方法 f(CallBack callback) ——A類調(diào)用B類的某個(gè)方法 C
5.然后b就可以在f(CallBack callback)方法中調(diào)用A的方法 ——B類調(diào)用A類的某個(gè)方法D
Java「關(guān)上了一扇門,必然會(huì)為你開啟另一扇窗」,而這扇窗就是「接口」。我們通過下面的例子來說明,在 Java 中,調(diào) Java 回調(diào)機(jī)制的演示(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);
}
}
保存并運(yùn)行程序,結(jié)果如下圖所示。

代碼詳解
第 01~04 行,聲明了一個(gè)接口 CallBack,在這個(gè)接口中聲明了一個(gè)抽象方法 methodToCallBack( )。
第 05~11 行,用一個(gè)名為 CallBackImpl 的類,實(shí)現(xiàn)了接口 CallBack。
第 12~24 行,設(shè)計(jì)了一個(gè)主調(diào)類 Caller,其中第 14~17 行聲明了一個(gè)注冊方法 register(),特別需要注意的是,這個(gè)方法的參數(shù)是接口對象 CallBack 的引用。
第 20 行,新建了一個(gè) Caller 對象,第 21 行新建了一個(gè) CallBackImpl 的對象,它是接口 CallBack 的具體實(shí)現(xiàn)者。
第 22 行,調(diào)用注冊方法 register(),實(shí)參就是 CallBackImpl 的對象 callBack,因?yàn)?CallBackImpl 實(shí)現(xiàn)(某種程度上可以說是繼承)了抽象接口,所以在 register()方法中,callBack 可以調(diào)用 methodToCallBack()方法。
或許,讀者會(huì)困惑,為什么不在第 21 行之后這么做。
callback.methodToCallBack()
這樣豈不是更加簡便?的確如此。
但這段代碼不在于如何用最短的代碼實(shí)現(xiàn)具體功能,而是為了給我們展示一下,如何在 Java 環(huán)境下實(shí)現(xiàn)一個(gè)回調(diào)機(jī)制。
我們知道,回調(diào)機(jī)制的真正意圖,其實(shí)是為了實(shí)現(xiàn)「控制反轉(zhuǎn)(Inversion of Control)」。通過控制反轉(zhuǎn),對象在被創(chuàng)建的時(shí)候(如第 21 行),由一個(gè)能夠調(diào)控系統(tǒng)內(nèi)所有對象的外界實(shí)體(如第 20 行的 caller),將其所依賴的對象的引用傳遞給功能方法塊(如第 22 行的 callBack,被送入到 register()中)。
我們知道,同一個(gè)接口,可以有不同的實(shí)現(xiàn)類,從而使得這些不同的實(shí)現(xiàn)類,可以定義眾多不同的對象,而這些對象會(huì)被按需「注入」功能方法塊 register()。在被調(diào)用前,這些對象永遠(yuǎn)處于等待調(diào)用狀態(tài),直到有一天被回調(diào)(callback)。
由上分析可知,控制反轉(zhuǎn)可以用來降低計(jì)算機(jī)代碼之間的耦合度。總結(jié)起來,回調(diào)的核心就是回調(diào)方將本身即this傳遞給調(diào)用方,這樣調(diào)用方就可以在調(diào)用完畢之后告訴回調(diào)方它想要知道的信息。回調(diào)是一種思想、是一種機(jī)制,至于具體如何實(shí)現(xiàn),如何通過代碼將回調(diào)實(shí)現(xiàn)得優(yōu)雅、實(shí)現(xiàn)得可擴(kuò)展性比較高,一看開發(fā)者的個(gè)人水平,二看開發(fā)者對業(yè)務(wù)的理解程度。觀看本站的Java接口教程,學(xué)習(xí)Java接口的回調(diào)機(jī)制,在你的代碼中實(shí)現(xiàn)Java接口的回調(diào)吧!

初級 202925

初級 203221

初級 202629

初級 203743