所謂回調,就是允許客戶類通過內部類引用來調用其外部類的方法,這是一種非常靈活的功能。
由於java暫時還不能顯示支持閉包(Closure),不過聽說新版可以支持了,不過我還沒用過。現在暫時用的是非靜態內部類實現回調功能。
情形一:
假設有一個老師Teacher對象,平時的工作是上課,週末的工作在家幹農活(鄉村老師大部分都這樣),方法名都是work,但功能都不一樣,可以用內部類實現這種需求:
- public class Teacher {
- // 正常的工作
- public void work() {
- System.out.println("平常我在給學生教課");
- }
- // 業餘的工作
- public void farming() {
- System.out.println("週末我在農田忙活");
- }
- private class Farmer {
- // 非靜態內部類回調外部類實現work方法,非靜態內部類引用的作用僅僅是向客戶提供一個回調外部類的途徑
- public void work() {
- farming();
- }
- }
- public Farmer getCallbackReference() {
- return new Farmer();
- }
- public static void main(String[] args) {
- Teacher t = new Teacher();
- // 直接調用work
- t.work();
- // 表面上調用的是Farmer的work方法,實際上是回調Teacher的farming方法
- t.getCallbackReference().work();
- }
- }
情形二:
Swing中響應按鈕點擊事件,使用匿名內部類,各個不同的控件發生事件後可以回調外部類中對應的處理方法。
- public class ButtonFrame extends JFrame {
- // 紅色按鈕
- private JButton redButton = new JButton("Red Button");
- // 藍色按鈕
- private JButton blueButton = new JButton("Blue Button");
- // 處理紅色按鈕的方法
- private void processRedButton() {
- System.out.println("紅色按鈕被點擊了");
- }
- // 處理藍色按鈕的方法
- private void processBlueButton() {
- System.out.println("藍色按鈕被點擊了");
- }
- public ButtonFrame() {
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- redButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- // 回調ButtonFrame中處理紅色按鈕的方法
- processRedButton();
- }
- });
- blueButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- // 回調ButtonFrame中處理藍色按鈕的方法
- processBlueButton();
- }
- });
- getContentPane().add(redButton);
- getContentPane().add(redButton);
- }
- public static void main(String[] args) {
- new ButtonFrame().setVisible(true);
- }
- }
最後,順便提一下C語言中實現這種回調的機制,就是利用函數指針的方式實現的。在《Pointers On C》這本書裏面舉了一個例子很詳細的說明這個問題:
要編寫一個類型無關的函數,在一個鏈表中查找一個指定的值,這個鏈表的數據元素可以是整數,也可能是字符串等,所以函數的參數就不能特定類型,C語言裏面有個void類型,可以指向任何類型,通過這個,可以編寫一個與類型無關的鏈表查找函數:
- /**
- * 在一個單鏈表中查找一個指定值的函數。它的參數是一個指向鏈表第1個節點的指針,
- * 一個指向我們需要查找的指針和一個函數的指針,它所指向的函數用於比較存儲於鏈表
- * 中的類型的值
- *
- */
- #include <stdio.h>
- #include <node.h>
- /*類型無關的鏈表查找*/
- Node * search_list() (Node *node, void const *value,
- int (*compare) (void const *, void const *)) {
- while (node != NULL) {
- if (compare( &node->value, value) == 0) {
- break;
- }
- node = node->link;
- }
- return node;
- }