最近学习内部类的时候,对Java实现回调函数机制有了进一步了解,自己整理点比较,希望大家可以相互讨论。
所谓回调,就是允许客户类通过内部类引用来调用其外部类的方法,这是一种非常灵活的功能。
由于java暂时还不能显示支持闭包(Closure),不过听说新版可以支持了,不过我还没用过。现在暂时用的是非静态内部类实现回调功能。
情形一
假设有一个老师Teacher对象,平时的工作是上课,周末的工作在家干农活(乡村老师大部分都这样),方法名都是work,但功能都不一样,可以用内部类实现这种需求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class Teacher { public void work() { System.out.println("平常我在给学生教课"); }
public void farming() { System.out.println("周末我在农田忙活"); }
private class Farmer { public void work() { farming(); } }
public Farmer getCallbackReference() { return new Farmer(); }
public static void main(String[] args) { Teacher t = new Teacher(); t.work(); t.getCallbackReference().work(); } }
|
情形二
Swing中响应按钮点击事件,使用匿名内部类,各个不同的控件发生事件后可以回调外部类中对应的处理方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| 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) { processRedButton(); } }); blueButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { processBlueButton(); } }); getContentPane().add(redButton); getContentPane().add(redButton); }
public static void main(String[] args) { new ButtonFrame().setVisible(true); } }
|
最后,顺便提一下C语言中实现这种回调的机制,就是利用函数指针的方式实现的。在《Pointers On C》这本书里面举了一个例子很详细的说明这个问题:
要编写一个类型无关的函数,在一个链表中查找一个指定的值,这个链表的数据元素可以是整数,也可能是字符串等,所以函数的参数就不能特定类型,C语言里面有个void类型,可以指向任何类型,通过这个,可以编写一个与类型无关的链表查找函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#include ; #include ;
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; }
|