将lambda传递给Timer而不是TimerTask

时间:2016-06-22 14:14:19

标签: java lambda java-8

我想在地图上执行延迟操作,所以我使用Timer,我传递的是TimerTask,延迟时间是毫秒:

timer.schedule(new TimerTask() {
    public void run() {
        tournaments.remove(id);
    }
}, delay);

这是一种类似原始缓存的功能,我在刚刚创建的新资源上设置了到期时间。

我以为我可以使用lambdas做到这一点,如下所示:

times.schedule(() -> tournaments.remove(id), delay);

但是编译器说这不可能。为什么?我究竟做错了什么?我可以使用lambdas来实现更简洁的代码,或者在这里根本不可能,我应该坚持使用匿名类吗?

2 个答案:

答案 0 :(得分:10)

为了使用lambda表达式,您需要一个必须是SAM类型的目标类型,即功能接口。由于TimerTask是一个抽象类,所以你不能在这里使用lambdas 使用lambda表达式可以做的是编写一个实用函数,将代码包装成TimerTask,如:

private static TimerTask wrap(Runnable r) {
  return new TimerTask() {

    @Override
    public void run() {
      r.run();
    }
  };
}

然后你可以使用你的lambda:

times.schedule(wrap(() -> tournaments.remove(id)), delay);

答案 1 :(得分:9)

TimerTask不是SAM(单一抽象方法)类型 - 现在,这听起来很矛盾,因为TimerTask上只有一个抽象方法!但是因为抽象父类实现了cancelscheduledExecutionTime,即使它们不是抽象的,编译器也不能采用你的lambda并创建一个匿名子类型TimerTask

可以做的是具有单个抽象方法和一个或多个默认方法的接口的lambdas,但遗憾的是TimerTask是一个较旧的类,并且不使用默认的方法功能Java 8。