認識Java的回調函數

在學習內部類的時候,對java實現回調函數機制有了進一步瞭解,自己整理點比較,希望大家可以相互討論。
所謂回調,就是允許客戶類通過內部類引用來調用其外部類的方法,這是一種非常靈活的功能。
由於java暫時還不能顯示支持閉包(Closure),不過聽說新版可以支持了,不過我還沒用過。現在暫時用的是非靜態內部類實現回調功能。

情形一:
假設有一個老師Teacher對象,平時的工作是上課,週末的工作在家幹農活(鄉村老師大部分都這樣),方法名都是work,但功能都不一樣,可以用內部類實現這種需求:
Java代碼  收藏代碼
  1. public class Teacher {  
  2.     // 正常的工作  
  3.     public void work() {  
  4.         System.out.println("平常我在給學生教課");  
  5.     }  
  6.   
  7.     // 業餘的工作  
  8.     public void farming() {  
  9.         System.out.println("週末我在農田忙活");  
  10.     }  
  11.   
  12.     private class Farmer {  
  13.         // 非靜態內部類回調外部類實現work方法,非靜態內部類引用的作用僅僅是向客戶提供一個回調外部類的途徑  
  14.         public void work() {  
  15.             farming();  
  16.         }  
  17.     }  
  18.   
  19.     public Farmer getCallbackReference() {  
  20.         return new Farmer();  
  21.     }  
  22.   
  23.     public static void main(String[] args) {  
  24.         Teacher t = new Teacher();  
  25.         // 直接調用work  
  26.         t.work();  
  27.         // 表面上調用的是Farmer的work方法,實際上是回調Teacher的farming方法  
  28.         t.getCallbackReference().work();  
  29.     }  
  30. }  



情形二:
Swing中響應按鈕點擊事件,使用匿名內部類,各個不同的控件發生事件後可以回調外部類中對應的處理方法。

Java代碼  收藏代碼
  1. public class ButtonFrame extends JFrame {  
  2.     // 紅色按鈕  
  3.     private JButton redButton = new JButton("Red Button");  
  4.     // 藍色按鈕  
  5.     private JButton blueButton = new JButton("Blue Button");  
  6.   
  7.     // 處理紅色按鈕的方法  
  8.     private void processRedButton() {  
  9.         System.out.println("紅色按鈕被點擊了");  
  10.     }  
  11.   
  12.     // 處理藍色按鈕的方法  
  13.     private void processBlueButton() {  
  14.         System.out.println("藍色按鈕被點擊了");  
  15.     }  
  16.   
  17.     public ButtonFrame() {  
  18.         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  19.         redButton.addActionListener(new ActionListener() {  
  20.             public void actionPerformed(ActionEvent e) {  
  21.                 // 回調ButtonFrame中處理紅色按鈕的方法  
  22.                 processRedButton();  
  23.             }  
  24.         });  
  25.         blueButton.addActionListener(new ActionListener() {  
  26.             public void actionPerformed(ActionEvent e) {  
  27.                 // 回調ButtonFrame中處理藍色按鈕的方法  
  28.                 processBlueButton();  
  29.             }  
  30.         });  
  31.         getContentPane().add(redButton);  
  32.         getContentPane().add(redButton);  
  33.     }  
  34.   
  35.     public static void main(String[] args) {  
  36.         new ButtonFrame().setVisible(true);  
  37.     }  
  38. }  

 

最後,順便提一下C語言中實現這種回調的機制,就是利用函數指針的方式實現的。在《Pointers On C》這本書裏面舉了一個例子很詳細的說明這個問題:

要編寫一個類型無關的函數,在一個鏈表中查找一個指定的值,這個鏈表的數據元素可以是整數,也可能是字符串等,所以函數的參數就不能特定類型,C語言裏面有個void類型,可以指向任何類型,通過這個,可以編寫一個與類型無關的鏈表查找函數:

C代碼  
  1. /** 
  2. * 在一個單鏈表中查找一個指定值的函數。它的參數是一個指向鏈表第1個節點的指針, 
  3. * 一個指向我們需要查找的指針和一個函數的指針,它所指向的函數用於比較存儲於鏈表  
  4. * 中的類型的值  
  5. * 
  6. */  
  7.   
  8. #include <stdio.h>  
  9. #include <node.h>  
  10.   
  11. /*類型無關的鏈表查找*/  
  12. Node * search_list() (Node *node, void const *value,  
  13.     int (*compare) (void const *, void const *)) {  
  14.         while (node != NULL) {  
  15.             if (compare( &node->value, value) == 0) {  
  16.                 break;  
  17.             }  
  18.             node = node->link;  
  19.         }  
  20.         return node;  
  21.     }  
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章