将 lambda 传递给计时器而不是计时器任务

2022-09-01 15:19:08

我想在地图上执行延迟操作,因此我正在使用,我正在向其传递一个和以毫秒为单位的延迟:TimerTimerTask

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

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

我认为我可以使用lambdas做到这一点,就像下面这样:

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

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


答案 1

TimerTask不是 SAM(单抽象方法)类型 -- 现在,这听起来很矛盾,因为 TimerTask 上只有一个抽象方法!但是,由于抽象父类实现 和 ,即使它们不是抽象的,编译器也无法获取您的 lambda 并创建 一个匿名的子类型 。cancelscheduledExecutionTimeTimerTask

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


答案 2

为了使用lambda表达式,您需要一个目标类型,该类型必须是SAM类型,即功能接口。由于 是 一个抽象类,因此您不能在此处使用 lambda。
要使用 lambda 表达式,您可以做的是编写一个实用程序函数,该函数将您的代码包装成如下:TimerTaskTimerTask

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

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

然后,您可以使用您的 lambda:

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

推荐