web-dev-qa-db-ja.com

コールバックを処理するjava8機能インターフェース

一般的なタスクを実行し、他のメソッドで使用される一般的なプライベートメソッドがあります。ジェネリックメソッドには、呼び出される他のメソッドをサポートするifおよびelse条件があります。例:

private void myGenericMethod(String name, int age){
  common task1;
  common task2;
  if(name!= null && name.length > 0){
     specific task 1;
     specific task 2;
  } else{
     specific task 3;
     specific task 4;
  }
  if(age > 18){
     specific task 1`;
     specific task 2`;
  }
}

Java 8 lambdaを使用し、Invokerメソッドでinvokeと呼ばれる機能インターフェイスを作成しました。

public interface Invoker{
  public void invoke()
}

これで、私の汎用メソッドは次のようになり、パブリックメソッドがinvoke関数のコールバックを適切に処理します。

private void myGenericMethod(Invoker invoker){
  common task1;
  common task2;
  invoker.invoke();
}  

自分でこのインターフェイスを作成する代わりに使用できる機能的なインターフェイスがJDKにありますか?

9
zilcuanu

パッケージ Java.util.function には、パラメーターを必要とせずvoidを返すメソッドとの機能的なインターフェースが含まれていません。ただし、代わりに Runnable インターフェースを使用できます。

private void myGenericMethod(Runnable runnable){
    common task1;
    common task2;
    //consider checking if runnable != null to avoid NPE
    runnable.run();
}  

次に、呼び出しは非常に簡単になります。

myGenericMethod(() -> {
    //do something fancy
    System.out.println("Hello, world!");
});

他のオプション

あなたが興味を持っているかもしれない他の機能的なインターフェースがあります、例えば:

  • Supplier<T> パラメータを渡さずにTの値を返したい場合
  • Function<T,R>Tの値を渡し、Rの値を返す場合
  • Consumer<T>Tをパラメーターとして渡し、voidを返す場合

なぜRunnableインターフェースに代わるものがないのですか?

Runnableインターフェースを使用して、何も返さず、パラメーターを期待しないラムダを使用すると、多くのプログラマーにとって物議をかもします。 Runnableは、別のスレッドでコードを実行するために考案されたもので、多くのプログラマーがこのクラスをマルチスレッドで識別しています。でも ドキュメント 言う:

Runnableインターフェイスは、インスタンスがスレッドによって実行されることを目的とするクラスによって実装される必要があります。

誰か すでに同様の質問をしました 2年前に このコメントBrian Goetz's を見てみると、それに対する理解がわかりますJava言語設計者は、Runnableインターフェイスの実装を模倣する別の機能インターフェイスを作成する必要がないという結論に達しました。

24
Szymon Stepniak

Consumer<Void>を使用する可能性もあります。こんな感じ

public void init(Consumer<Void> callback) {
    callback.accept(null);
}

init((Void) -> done());
2
Murat Karagöz

Consumerをコールバックインターフェイスとして使用することをお勧めします。 JavaScript言語と比較すると、コールバックはスコープにバインドされています。したがって、Consumerインターフェイスを使用する場合は、スコープをパラメーターとして関数に渡すことができます。例:

public void startTracer(String tracerName, Event boundEvent) {
    executeOnTracer(tracer -> tracer.startTracer(tracerName, boundEvent));
}
...
private void executeOnTracer(Consumer<Tracer> callback) {
    TracerController tracer = null;
    if (isTracerActive()) {
        tracer = getTracer();
    }
    Optional.ofNullable(tracer).ifPresent(callback::accept);
}
0