正如您所知,您可以在Java 8中使用lambdas,例如替换匿名方法。
这里可以看到Java 7与Java 8的一个例子:
Runnable runnable = new Runnable() {
@Override
public void run() {
checkDirectory();
}
};
可以用Java 8中的以下两种方式表示:
Runnable runnable = () -> checkDirectory();
或
Runnable runnable = this::checkDirectory;
这是因为Runnable
是一个功能接口,只有一个(抽象)公共非默认方法。
然而......对于TimerTask
,我们有以下内容:
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
checkDirectory();
}
};
看起来很熟悉吧?
但是使用lambda表达式不起作用,因为TimerTask
是一个抽象类,即使它只有一个抽象的公共非默认方法,它也不是一个接口,因此也没有功能接口。
它也没有重构为具有默认实现的接口,因为它带有状态,因此无法完成。
所以我的问题:构建TimerTask
时有没有办法使用lambdas?
我想要的是以下内容:
Timer timer = new Timer();
timer.schedule(this::checkDirectory, 0, 1 * 1000);
而不是一些丑陋的匿名内部类,有没有办法让它变得更好?
答案 0 :(得分:11)
首先注意到Timer
实际上是一个过时的API,但是尽管如此,你可以在它周围写一个小包装器,它会调整schedule
方法来接受Runnable
,在内部,你将Runnable
变成TimerTask
。那么你将拥有接受lambda的schedule
方法。
public class MyTimer {
private final Timer t = new Timer();
public TimerTask schedule(final Runnable r, long delay) {
final TimerTask task = new TimerTask() { public void run() { r.run(); }};
t.schedule(task, delay);
return task;
}
}
答案 1 :(得分:0)
要完成Marko Topolnik关于Timer
的回答,您只需使用lambda调用schedule
方法。
schedule(() -> {
System.out.println("Task #1 is running");
}, 500);
答案 2 :(得分:0)
虽然Marko的答案是完全正确的,但我更喜欢我的实现方式:
public class FunctionalTimerTask extends TimerTask {
Runnable task;
public FunctionalTimerTask(Runnable task) {
this.task = task;
}
@Override
public void run() {
task.run();
}
}
public static class Task {
public static TimerTask set(Runnable run) {
return new FunctionalTimerTask(() -> System.err.println("task"));
}
}
Timer timer = new Timer(false);
timer.schedule(Task.set(() -> doStuff()), TimeUnit.SECONDS.toMillis(1));
这使您可以更好地控制计时器,并且具有静态实用程序类。从概念上讲,给它起一个不会与其他通用线程类冲突的名称,所以不要与Task,Job和Timer冲突。
答案 3 :(得分:0)
我知道这是一篇过时的文章,但为完整起见,我想包括wrapper solution发表的Flown:
private static TimerTask wrap(Runnable r) {
return new TimerTask() {
@Override
public void run() {
r.run();
}
};
}
那么您的通话可以变成:
timer.schedule(wrap(this::checkDirectory), delay);
答案 4 :(得分:-1)
如果需要,您也可以使用Swing API中的lambdas轻松创建一个Timer(但不能使用TimerTask):
new javax.swing.Timer(1000, (ae) -> this::checkDirectory).start();