接口与回调
回调(callback)是一种常见的程序设计模式。在这种模式中,可以指出某个特定事件发生时应该采取的动作。如,可以指出在按下鼠标或选择某个菜单项时应该采取什么行动。
在java.swing包中有一个Timer类,可以使用它在达到给定的时间间隔时发出通告。例如,假如程序中有一个时钟,就可以请求每秒钟获得一个通告,以便更新时钟的表盘。
在构造定时器时,需要设置一个时间间隔,并告之定时器,当达到时间间隔时需要做些什么操作。
如何告之定时器做什么呢?在很多程序设计语言中,可以提供一个函数名,定时器周期地调用它。但是,在Java标准类库中的类采用的是面向对象方法。它将某个类的对象传递给定时器,然后,定时器调用这个对象的方法。由于对象可以携带一些附加的信息,所以传递一个对象比传递一个函数要灵活很多。
当然,定时器需要知道调用哪一个方法,并要求传递的对象所属的类实现了java.awt.event包的ActionListener接口。
public interface ActionListener {
void actionPerformed(ActionEvent event);
}
当到达指定的时间间隔时,定时器就调用actionPerformed方法。
假设希望每隔10秒钟打印一条信息“At the tone, the time is …”,然后响一声,就应该定义一个实现ActionListener接口的类,然后将需要执行的语句放在actionPerformed方法中。
class TimePrinter implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("At the tone, the time is " + new Date());
Toolkit.getDefaultToolkit().beep();
}
}
接下来,构造这个类的对象,并将它传递给Timer构造器。
ActionListenere listener = new TimePrinter();
Timer t = new Timer(10000, listener);
Timer构造器的第一个参数是发出通告的时间间隔,它的单位是毫秒。这里希望每隔10秒钟通告一次。第二个参数是监听器对象。
最后,启动定时器:
t.start();
实例
这个程序将弹出一个消息对话框,并等待用户点击OK按钮来终止程序的执行。在程序等待用户操作的同时,每隔10s显示一次当前的时间。
运行这个程序时要有一些耐心。程序启动后,将会立即显示一个包含“Quit program?”字样的对话框,10秒钟之后,第1条定时器消息才会显示出来。
package cn.freedompc.timer;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import javax.swing.JOptionPane;
import javax.swing.Timer;
public class TimerTest {
public static void main(String[] args) {
ActionListener listener = new TimePrinter();
Timer t = new Timer(10000, listener);
t.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TimePrinter implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("At the tone, the time is " + new Date());
Toolkit.getDefaultToolkit().beep();
}
}
结果:
Comparator接口
我们之前已经了解了如何对一个对象数组排序,前提是这些对象是实现了Comparable接口的类的实例。例如,可以对一个字符串数组排序,因为String类实现了Comparator<String>,而且,String.compareTo方法可以按字典顺序比较字符串。
现在假设我们希望按长度递增的顺序对字符串进行排序,而不是按字典顺序进行排序。肯定不能让String类用两种不同的方式实现compareTo方法,更何况,String类也不应由我们来修改。
要处理这种情况,Arrays.sort方法还有第二个版本,有一个数组和一个比较器(comparator)作为参数,比较器是实现了Comparator接口的类的实例。
public interface Comparator<T> {
int compara(T first, T second);
}
要按长度比较字符串,可以如下定义一个实现Comparator<String>的类:
class LengthComparator implements Comparator<String> {
public int compare(String first, String second) {
return first.length - second.length();
}
}
具体完成比较时,需要建立一个实例:
Comparator<String> comp = new LengthComparator();
if (comp.compare(words[i], words[j]) > 0) ...
将这个调用与words[i].compareTo(words[j])做比较。这个compare方法在比较器对象上调用,而不是在字符串本省上调用。
捐赠
若你感觉读到这篇文章对你有启发,能引起你的思考。请不要吝啬你的钱包,你的任何打赏或者捐赠都是对我莫大的鼓励。