web-dev-qa-db-ja.com

ラムダでTimerTaskを使用する方法?

うまくいけば、Java 8でラムダを使用して、たとえば匿名メソッドを置き換えることができます。

Java 7 vs Java 8:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        checkDirectory();
    }
};

Java 8では、次の両方の方法で表すことができます。

Runnable runnable = () -> checkDirectory();

または

Runnable runnable = this::checkDirectory;

これは、Runnableが機能的なインターフェイスであり、デフォルト以外のパブリックメソッド(抽象)が1つしかないためです。

ただし... TimerTaskの場合、次のようになります。

TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        checkDirectory();
    }
};

おなじみですね。
ただし、ラムダ式を使用しても機能しません。TimerTaskは抽象クラスであるため、デフォルト以外のパブリックメソッドが1つしかなくても、インターフェースではないため、機能インターフェースもありません。 。
また、状態を運ぶため、デフォルトの実装ではインターフェイスにリファクタリングされないため、その場合は実行できません。

だから私のquestionTimerTaskを構築するときにラムダを使用する方法はありますか?

私が欲しかったのは以下です:

Timer timer = new Timer();
timer.schedule(this::checkDirectory, 0, 1 * 1000);

醜い匿名の内部クラスの代わりに、それをより良くする方法はありますか?

20
skiwi

最初にTimerは事実上時代遅れのAPIであることに注意してください。それでも質問を楽しませるには、scheduleメソッドを適合させてRunnableを受け入れる小さなラッパーを書くことができます。内側では、そのRunnableTimerTaskに変換します。次に、ラムダを受け入れる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;
  }
}
12
Marko Topolnik

マルコの答えは完全に正しいですが、私は私の実装を好みます:

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));

これにより、タイマーをより詳細に制御でき、静的なユーティリティクラスが作成されます。他の一般的なスレッドクラスと競合しない名前を付けてください。タスク、ジョブ、タイマーではありません。

0
Kalec

Marko TopolnikのTimerに関する回答を完了するには、ラムダを使用してscheduleメソッドを呼び出すだけです。

schedule(() -> {
    System.out.println("Task #1 is running");
}, 500);
0
François SAMIN