认识Java的回调函数

来源:互联网 发布:php 替换空格 编辑:程序博客网 时间:2024/06/06 19:05
在学习内部类的时候,对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.     }  
 
原创粉丝点击