什么是Java 8中的Functional接口?

功能接口是Java 8最重要的概念之一,它实际上支持lambda表达式,但许多开发人员没有花足够的精力去理解它并花时间学习lambda表达式和Stream API而没有先了解Java 8中函数接口的作用除非你知道什么是函数接口以及lambda如何与它相关,否则你不能使用Java 8的强大功能,例如lambda表达式和流API。如果没有功能接口的知识,你将无法理解在代码中可以使用lambda的位置,但是你也很难编写方法所期望的lambda表达式,因此,重要的是要对函数接口有一个很好的理解。 Java 8。


在本文中,我将尝试通过解释什么是函数接口,什么是@Functional注释,它们如何与lambda表达式相关以及它们如何帮助您在代码中使用lambda表达式来填补这一空白。那么,让我们从第一件事开始,什么是功能界面?


什么是Java 8中的Functional接口
嗯,功能界面只不过是一个只有一个抽象方法的界面,例如 Comparable,Runnable,EventListener,Comparator等。您甚至可以在JDK 8之前看到这些接口存在于Java中,但为什么我们称之为接口功能接口?


这是一个非常好的问题,如果您对函数式编程有一点了解,您就知道它允许您传递代码,即函数就像将数据或对象传递给方法一样。




这些只使用一个抽象方法的接口用于传递代码,就像在函数式编程语言中传递函数一样,这就是为什么它们被称为函数接口。


例如,您可以通过实现Comparator接口创建Anonymous类来直接传递代码来比较对象,如下所示:

Collections.sort(list, new Comparator(){

   public int compare(String s1, String s2){
      return s1.length() - s2.length();
   }
});

因此,如果仔细观察,您可以看到我们正在使用这些接口将代码传递给函数。它们也称为策略接口,因为它是策略模式的实现,其中形成策略的代码被注入到在运行时运行该策略的代码中。


顺便说一下,如果你不知道什么是策略模式,那么我建议你经历从0到1:设计模式 - 24重要 - 在Java中,因为设计模式的知识对于Java中的有效编码很重要。


Java中的策略模式




那么,既然我们知道什么是函数接口,那么让我们理解它们与lambda表达式的关系,以及如何理解函数接口对于使用lambda表达式编写代码很重要?


好吧,最重要的是要记住,在Java中使用lambda表达式只是将它们转换为功能接口。


这意味着如果方法接受功能接口,则可以传递lambda表达式,这进一步意味着,您可以将lambda传递给接受Comparator,Runnable或任何其他只有一个抽象方法的接口的所有现有方法。


这就是Java中lambda表达式也称为SAM类型的原因,其中SAM表示单一抽象方法。如果您想了解有关SAM类型的更多信息,那么您还可以查看Java SE 8 for Really Impatient By Cay S. Horstmann以了解有关Java中lambda表达式的更多信息


@Functional注释有什么作用?
现在,让我们看看@Functional注释做了什么?如果只是将@Functional注释置于其上,它是否会使界面起作用?嗯,不,它没有那样做。实际上,它是可选的。


这意味着您可以在不使用@Functioanl注释的情况下创建功能界面,就像您可以覆盖方法而不将@Override注释放在方法之上。那么@Functional注释的真正目的是什么?


好吧,它可以确保接口实际上只有一个抽象方法,并且它还为Javadoc这样的工具提供了一个提示,即该接口是一个功能接口。它与@Override注释非常相似,它通过验证您实际覆盖方法来帮助防止人为错误。


与@Override类似,它的最佳实践是使用单个抽象方法将@Functional注释置于方法之上,以向Javadoc等工具指示它们是一个功能接口。


java.util.function包中添加的所有新功能接口都使用@Functional注释进行注释。


顺便说一句,是的,我们在JDK 8中有更多的功能接口,特别是通用功能接口,如谓词,供应商,消费者,功能,BiFunction,UnaryOperator等。请参阅Java 8:初学者的基础知识,以深入了解所有这些接口。


这些功能接口允许您以lambda表达式的形式将代码传递给函数,并允许创建可以对这些代码进行操作的强大方法,例如filter()接受Predicate并允许您传递接受一个参数并返回布尔值的代码。

功能界面和Lamda表达式的关系如何
功能界面的知识如何影响lambda表达式的编写?好吧,除非你不理解功能接口,否则你不能写一个可以转换成该功能接口的lambda表达式。


例如,java.util.Map接口的merge()方法接受BiFunction,但如果你不知道BiFunction是什么,那么就不能为此编写lambda。


BiFunction是一个功能接口,它有一个接受两个参数T和U并返回一个对象R的方法。


这意味着您可以将lambda传递给此方法,该方法可以处理两个参数并返回一个对象,例如merge(key,value,(v1,v2) - > v1 + v2)here(v1,V2) - > v1 + v2是lambda表达式,可以转换为BiFunction功能接口的实例。


一个相当简单的例子是Predicate,它接受一个类型T并返回一个布尔值。如果你看一下Stream类的filter()方法,它接受一个Predicate:


过滤器(谓词谓词)


这意味着您可以传递任何接受一个参数的lambda表达式并将boolean返回给此方法,例如年龄 - >年龄> 15或s - > s.length == 15,两者都可以接受,但如果你不知道Predicate接口是什么,那你就不能这样做了。


功能接口的另一个例子是Consumer,它接受类型为T的参数并且不返回任何内容。在JDK 8中的Iterable的forEach()方法中可以很好地使用它,如下所示:


forEach(消费者行动)


你可以看到forEach()接受了一个Consumer,这意味着你可以传递一个lambda表达式,该表达式有一个参数并且不返回任何内容或者返回空格,例如


s - > System.out.println(s)


代码System.out.println()什么都不返回,它只是在控制台中打印行。


您可以看到,如果您知道功能接口,那么您可以轻松编写lambda表达式来传递,因此必须具备良好的功能接口知识。我建议你浏览java.util.function包中的所有功能界面并理解它们。


 我将在接下来的文章中解释java.util.function包中一些更复杂的功能接口,但是如果你不能等待,那么我建议你通过这个Java 9 Master Class课程来了解有关lambdas和其他Java的更多信息。 8个概念。




这就是Java中的功能接口。您还了解了@Functional注释的作用是什么以及为什么需要良好的功能接口知识才能在Java 8的代码中有效地使用lambda表达式。如果您还没有从Java 8开始,我建议您这样做它现在是因为在未来几年中,每个人都将使用Java 8进行编码,如果您不了解lambda表达式和Java 8中引入的新功能,那么您将被抛在后面。

你可能感兴趣的:(java)