java什么是回調(diào)
軟件模塊之間總是存在著一定的接口,從調(diào)用方式上,可以把他們分為三類:同步調(diào)用、回調(diào)和異步調(diào)用。同步調(diào)用是一種阻塞式調(diào)用,調(diào)用方要等待對方執(zhí)行完畢才返回,它是一種單向調(diào)用;回調(diào)是一種雙向調(diào)用模式,也就是說,被調(diào)用方在接口被調(diào)用時也會調(diào)用對方的接口;異步調(diào)用是一種類似消息或事件的機制,不過它的調(diào)用方向剛好相反,接口的服務(wù)在收到某種訊息或發(fā)生某種事件時,會主動通知客戶方(即調(diào)用客戶方的接口)。回調(diào)和異步調(diào)用的關(guān)系非常緊密,通常我們使用回調(diào)來實現(xiàn)異步消息的注冊,通過異步調(diào)用來實現(xiàn)消息的通知。同步調(diào)用是三者當(dāng)中最簡單的,而回調(diào)又常常是異步調(diào)用的基礎(chǔ),因此,下面我們著重討論回調(diào)機制在不同軟件架構(gòu)中的實現(xiàn)。
Java的回調(diào)簡單的說,回調(diào)函數(shù)就是通過其指針來調(diào)用的函數(shù)(這句話確實夠簡單的,下面會詳細(xì)的描述);回調(diào)函數(shù)不會被自己所在的對象調(diào)用,只會在調(diào)用別人的方法的時候反過來被調(diào)用。我們知道android程序是通過java來實現(xiàn)的,java中是沒指針的,那么怎么實現(xiàn)回調(diào)呢,通過接口、或者抽象類。
實現(xiàn)步驟:
1、定義一個接口,其中包含一個方法a;
2、定義一個實現(xiàn)這個接口的類A,實現(xiàn)方法 a(此處的a就是傳說中的回調(diào)函數(shù),此處不一定要在聲明類的時候?qū)崿F(xiàn)這個接口,也可以在類中去實現(xiàn)這個接口,我會分別舉例子)
3、定義一個類B,在B中定義一個方法b,b以第一步中定義的接口作為參數(shù);
4、在A中調(diào)用方法b,把自己作為參數(shù)傳遞進(jìn)去;
5、在B中通過傳遞進(jìn)來的參數(shù)A(實現(xiàn)了接口)去調(diào)用a,這就實現(xiàn)了回調(diào);
至于為什么要使用回調(diào)函數(shù)呢?在一位大神的博客里面看到這句話“回調(diào)功能是實現(xiàn)功能和定義分離的一種手段,是一種松耦合的設(shè)計思想”,有的人就會問了,為什么要實現(xiàn)定義和功能分離呢?我們在剛開始接觸面向?qū)ο蟮倪@個概念的時候,應(yīng)該經(jīng)常聽到這種說法:面向?qū)ο笫且獙崿F(xiàn)高內(nèi)聚、低耦合,方便程序的修改和擴展。我覺得函數(shù)的定義和功能的分離應(yīng)該也是這個道理吧。在下面的例子中我會在注釋中從另外一個方面說明回調(diào)函數(shù)的必要性。
其次,看代碼吧
代碼1,在聲明類的時候?qū)崿F(xiàn)接口:
[java] view plaincopypackage com.callback;
/* 第一步:定義一個接口,其中包含一個方法a*/
public interface Callback {
public void a(int i);
}
[java] view plaincopypackage com.callback;
/* 第二步:定義一個實現(xiàn)這個接口的類A,實現(xiàn)方法 a*/
public class A implements Callback{
static B b = new B();
/* 此處為什么要定義一個常量呢?
* 我是想從另一個方面(松耦合的設(shè)計思想算是一方面吧)說明回調(diào)方法的必要性,
* 暫時先不用管,后面會繼續(xù)說明的*/
final int Constant = 1;
@Override
/* 回調(diào)方法不會在A類中被調(diào)用的,注意看待會他會在哪被調(diào)用 */
public void a(int result) {
// TODO Auto-generated method stub
System.out.println(result);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
/* 第四步:在A中調(diào)用方法b,把自己作為參數(shù)傳遞進(jìn)去,
* 此處A中的常量Constant,也會隨著A被傳到B中*/
b.b(new A());
}
}