java8函数接口处理回调
Posted
技术标签:
【中文标题】java8函数接口处理回调【英文标题】:java8 functional interface to handle the callback 【发布时间】:2018-01-11 23:32:11 【问题描述】:我有一个通用的私有方法,它执行常见任务并被其他方法使用。泛型方法具有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,并且我使用 invoke
方法创建了一个名为 Invoker
的功能接口。
public interface Invoker
public void invoke()
现在我的通用方法看起来像这样,公共方法适当地处理调用函数回调:
private void myGenericMethod(Invoker invoker)
common task1;
common task2;
invoker.invoke();
JDK中有没有我可以使用的功能接口,而不是自己创建这个接口?
【问题讨论】:
您可以查看java.util.function
包并选择适合您要求的包。我不能推荐一个,因为我不知道你的具体任务是否有争论(或更多)等等......
【参考方案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!");
);
其他选项
还有其他你可能感兴趣的功能接口,例如:
Supplier<T>
如果你想在不传递任何参数的情况下返回 T
的值
Function<T,R>
如果要传递 T
的值并返回 R
的值
Consumer<T>
如果您想将值 T
作为参数传递并返回 void
为什么Runnable
接口没有替代品?
将Runnable
接口用于不返回任何内容且不期望任何参数的lambda 对许多程序员来说可能听起来有争议。 Runnable
是为在单独的线程中运行代码而发明的,许多程序员将此类标识为多线程。甚至documentation 说:
Runnable
接口应该由其实例打算由线程执行的任何类实现。
有人already asked similar question 2 年前,如果你看看this comment 和Brian Goetz's 对它的反应,你就会明白Java 语言设计者得出的结论是没有必要创建另一个模仿的功能接口Runnable
接口的实现。
【讨论】:
Runnable
旨在封装可以异步完成的工作。在这种情况下使用它是令人困惑的[需要引用]。如果意图被其他开发人员误解,可能会导致严重的问题。有人建议创建自己的界面,称为 Operation
、Executable
或类似的名称。
如果您使用“调用”术语,我建议改用接口名称 Invokable
,以符合命名约定。
我不想使用Runnable
的原因是当他们看到 Runnable 并造成混乱时,它会引起共同开发人员的眉毛。我会坚持使用 Invokable。但令我惊讶的是Java8没有这样的接口
是的,java.util.function
中应该有一个。在这种情况下,最好使用您的自定义选项。
@zilcuanu Brian Goetz 解释了为什么这里没有 Runnable
接口的替代品 - ***.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);
【讨论】:
以上是关于java8函数接口处理回调的主要内容,如果未能解决你的问题,请参考以下文章
Java8中的函数式接口SupplierConsumerBiConsumer详解