用于处理回调的java8功能接口

时间:2017-08-04 06:42:11

标签: java generics lambda java-8

我有一个通用的私有方法,它执行常见任务并被其他方法使用。泛型方法具有ifelse条件,以支持所调用的其他方法。例如:

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()
}

现在我的泛型方法看起来像这样,公共方法适当地处理调用函数回调:

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

我可以使用JDK中的功能接口而不是自己创建这个接口吗?

3 个答案:

答案 0 :(得分:19)

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接口没有其他选择?

对于没有返回任何内容并且不期望任何参数的lambda使用Runnable接口可能对许多程序员来说都是有争议的。 Runnable是为在单独的线程中运行代码而发明的,许多程序员使用多线程来识别这个类。即使documentation说:

  

Runnable接口应由任何其实例打算由线程执行的类实现。

2年前有人already asked similar question如果你看看this commentBrian Goetz's对它的反应,你就会明白Java语言设计师得出的结论是没有必要创建另一个模仿Runnable接口实现的功能接口。

答案 1 :(得分:1)

也可以使用Consumer<Void>。看起来像这样

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

init((Void) -> done());

答案 2 :(得分:0)

我建议使用Consumer作为回调接口。与JavaScript语言相比,回调是通过范围绑定的。因此,如果您使用使用者接口,则可以将范围作为参数传递给函数。 例如:

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