1. 程式人生 > 其它 >Java核心技術讀書筆記6-2 什麼是回撥(callback)與回撥函式?以及如何用Java實現?

Java核心技術讀書筆記6-2 什麼是回撥(callback)與回撥函式?以及如何用Java實現?

2.回撥

2.1 什麼是回撥
在電腦科學中,回撥函式是指一段以引數的形式傳遞給其它程式碼的可執行程式碼。簡單地說,函式A的引數是一個函式,在A中執行這個引數函式的形式與過程就是回撥其中作為引數傳入函式A的函式就是回撥函式。一般在應用開發過程中,我門是負責編寫回調函式的。將函式傳入其它函式,要求其它類庫函式或者系統執行我們的函式。那麼為什麼我們不能直接呼叫這個服務呢?同時,如果要是讓我們編寫函式A我們該如何做呢?為什麼我們不能直接在函式中呼叫作為引數的那個函式呢?
舉個例子:我們現在有一個函式,功能是能夠識別杯子容量並自動打水的飲水機,而作為回撥函式,其功能是擰開一個杯子,並返回其容量。那麼我們的兩個函式虛擬碼可以這樣寫:

//不同的將要作為回撥函式的函式
int fun 開啟礦泉水瓶(){
  擰開瓶蓋;
  調整瓶子狀態;
  return 250;
}
int fun 開啟暖壺(){
  開啟外蓋;
  開啟木塞;
  調整瓶子狀態;
  return 2000;
}
int fun 開啟飲水瓶(){
  開啟開關;
  按下按鈕;
  調整瓶子狀態;
  return 500;
}
//提供打水服務的函式
void fun 智慧飲水機(fun f1){
  啟動機器識別功能
  int volume = f1; //執行回撥函式
  開啟開關;
  放水volume毫升; //本函式提供的服務
  關閉開關;
}

那麼為什麼我們的回撥函式不能直接呼叫這個服務呢?或者為什麼我們不能直接在函式中呼叫作為引數的那個函式呢?因為可以把函式提供的功能當成一種通用的服務,而請求者(回撥函式)確是可能各不相同且未知的,對於未知的請求者我們無法寫出針對他的程式碼,不過只要他遵守一定的規則(如上面的返回一個整型)就可以呼叫這個服務。
如果還不理解,可以再看看這篇文章:回撥函式(callback)是什麼? - 碼農的荒島求生的回答 - 知乎

https://www.zhihu.com/question/19801131/answer/1641403537

2.2 如何用Java實現回撥
對於回撥,主要就是要把函式作為引數傳入到另一個函式中,在C/C++中這個很容易用函式指標實現。在Java中,由於面向物件的特性,可以將一個具有特定回撥函式的物件傳入到方法中,然後在方法中呼叫這個物件的特定回撥函式(方法)。那麼如何確保該物件一定擁有這個特定的回撥函式呢?我們知道可以用介面提供一組規範來要求實現類具有某些行為,所以,我們可以要求傳入的物件的類必須實現了具有回撥函式的介面。而在Java中,一個介面型別變數可以指向任何實現了該介面的類的物件,所以我們只需把函式的引數寫成介面型別的變數就可以。
之前打水機的例子用java實現為:

//介面
public interface Openable{ 
  int openBottle();
}
//一個實現類
public Class Thermos implements Openable{
  ...
  public int openBottle(){ //作為回撥函式
    do something...
    return 500;
  }
  ...
}
//提供打水服務的方法
 public void draw_water(Openable bottle){
  do something...
  int volume = bottle.openBottle(); //執行回撥函式(物件的方法)
  do something...
}