【问题标题】:java8 functional interface to handle the callbackjava8函数接口处理回调
【发布时间】:2018-01-11 23:32:11
【问题描述】:

我有一个通用的私有方法,它执行常见任务并被其他方法使用。泛型方法具有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,并且我使用 invoke 方法创建了一个名为 Invoker 的功能接口。

public interface Invoker{
  public void invoke()
}

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

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

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

【问题讨论】:

  • 您可以查看java.util.function 包并选择适合您要求的包。我不能推荐一个,因为我不知道你的具体任务是否有争论(或更多)等等......

标签: java generics lambda java-8


【解决方案1】:

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

其他选项

还有其他你可能感兴趣的功能接口,例如:

为什么Runnable接口没有替代品?

Runnable 接口用于不返回任何内容且不期望任何参数的lambda 对许多程序员来说可能听起来有争议。 Runnable 是为在单独的线程中运行代码而发明的,许多程序员将此类标识为多线程。甚至documentation 说:

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

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

【讨论】:

  • Runnable 旨在封装可以异步完成的工作。在这种情况下使用它是令人困惑的[需要引用]。如果意图被其他开发人员误解,可能会导致严重的问题。有人建议创建自己的界面,称为 OperationExecutable 或类似的名称。
  • 如果您使用“调用”术语,我建议改用接口名称 Invokable,以符合命名约定。
  • 我不想使用Runnable 的原因是当他们看到 Runnable 并造成混乱时,它会引起共同开发人员的眉毛。我会坚持使用 Invokable。但令我惊讶的是Java8没有这样的接口
  • 是的,java.util.function 中应该有一个。在这种情况下,最好使用您的自定义选项。
  • @zilcuanu Brian Goetz 解释了为什么这里没有 Runnable 接口的替代品 - stackoverflow.com/questions/27973294/… 引用:“我确信 Runnable 的存在是 Java 设计人员认为他们没有'不需要添加另一个功能接口”,Brian 证实了这一点。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    我建议使用 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      相关资源
      最近更新 更多