在 Java8中函数式接口是用来做什么的?

我在 Java8中遇到了一个新术语: “函数式接口”。在使用 Lambda 表达式时,我只能找到它的一种用法。

Java8提供了一些内置的函数式接口,如果我们想定义任何函数式接口,那么我们可以使用 @FunctionalInterface注释。它只允许我们在接口中声明一个方法。

例如:

@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}

除了使用 Lambda 表达式之外,它在 Java8中有多大用处?

(问题 给你是不同的一个我问。这就是为什么我们在使用 lambda 表达式时需要函数式接口。我的问题是: 除了使用 lambda 表达式之外,函数接口还有哪些其他用途?)

145552 次浏览

一点也不,Lambda 表达式是注释的唯一要点。

@FunctionalInterface注释对于代码的编译时检查非常有用。除了 staticdefault和抽象方法以外,不能有多个方法覆盖 @FunctionalInterfaceObject中的方法或任何其他用作函数接口的接口。

但是您可以在不使用此注释的情况下使用 lambdas,也可以在不使用 @Override注释的情况下重写方法。

从医生那里

一个函数接口只有一个抽象方法 方法有一个实现,它们不是抽象的 声明一个抽象方法,该方法重写 对象,这也不计入接口的 抽象方法计数,因为接口的任何实现都将 有一个来自 java.lang.Object 或其他地方的实现

这个用 lambda 表达的 可以使用:

public interface Foo {
public void doSomething();
}

这个用 lambda 表达的 不能使用:

public interface Foo {
public void doSomething();
public void doSomethingElse();
}

但这将给 编译错误带来:

@FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}

无效的“@FunctionalInterface”注释; Foo 不是函数 接口

可以将 lambda 表达式分配给函数接口类型,也可以将方法引用和匿名类分配给函数接口类型。

java.util.function中特定函数接口的一个好处是,由于它们包含的方便的默认方法,可以组合它们来创建新函数(如 Function.andThenFunction.composePredicate.and等)。

文件确实使目的有所不同

一种提供信息的注释类型,用于指示接口类型声明应该是由 Java 语言规范定义的 功能界面

和用例

注意,可以使用 lambda 表达式、方法引用或构造函数引用创建函数接口的实例。

其措辞一般不排除其他用例。由于主要用途是指示 功能界面,因此实际的问题可归结为 ”是否有其他用例函数接口 除了 lambda 表达式和方法/构造函数引用?”

由于 功能界面是 Java 语言规范定义的 Java 语言构造,因此只有该规范可以回答这个问题:

JLS 9.8. 函数式接口 :

...

除了通过声明和实例化类(15.9)来创建接口实例的常规过程之外,还可以使用方法引用表达式和 lambda 表达式(15.13,15.27)来创建函数接口实例。

因此,Java 语言规范没有另外说明,该部分中提到的唯一用例是使用方法引用表达式和 lambda 表达式创建接口实例。(这包括构造函数引用,因为它们是规范中方法引用表达式的一种形式)。

所以在一句话中,没有,在 Java8中没有其他的用例。

正如其他人所说,函数式接口是公开一种方法的接口。它可能有多个方法,但所有其他方法都必须有一个默认实现。它之所以被称为“函数式接口”,是因为它有效地充当了函数的角色。由于可以将接口作为参数传递,这意味着函数现在像函数式编程语言一样是“一等公民”。这有很多好处,在使用 StreamAPI 时您会看到很多好处。当然,lambda 表达式是它们的主要用途。

@FunctionalInterface是用 Java8发布的一个新注释,它为 lambda 表达式提供目标类型,并用于代码的编译时检查。

当你想使用它的时候:

1-您的接口 不可以有多个抽象方法,否则将给出编译错误。

1-你的接口 应该是纯的,这意味着函数式接口是由无状态类实现的,纯的例子是 Comparator接口,因为它不依赖于实现者的状态,在这种情况下 没有编译错误将被给出,但在许多情况下,你不能使用 lambda 与这种接口

java.util.function包包含各种通用功能接口,如 PredicateConsumerFunctionSupplier

还请注意,您可以使用没有这个注释的 lambdas。

除了其他答案,我认为“为什么使用 Functional Interface 而不是直接使用 lambda 表达式”的主要原因可能与 Java 语言的面向对象特性有关。

Lambda 表达式的主要属性是: 1。它们可以在2点左右传递。并且它们可以在将来的特定时间内(多次)执行。现在,为了在语言中支持这个特性,其他一些语言只是简单地处理这个问题。

例如,在 JavaScript 中,函数(匿名函数或函数文字)可以作为对象进行处理。因此,您可以简单地创建它们,也可以将它们分配给一个变量等等。例如:

var myFunction = function (...) {
...;
}
alert(myFunction(...));

或通过 ES6,你可以使用箭头功能。

const myFunction = ... => ...

到目前为止,Java 语言设计人员还没有接受通过这些方式(函数式编程技术)来处理上述特性。他们相信 Java 语言是面向对象的,因此他们应该通过面向对象技术来解决这个问题。他们不想错过 Java 语言的简单性和一致性。

因此,它们使用接口,就像当只有一个方法(我的意思是函数式接口)的接口对象需要时,可以用 lambda 表达式替换它。例如:

ActionListener listener = event -> ...;

可以在 Java8中使用 lambda

public static void main(String[] args) {
tentimes(inputPrm - > System.out.println(inputPrm));
//tentimes(System.out::println);  // You can also replace lambda with static method reference
}


public static void tentimes(Consumer myFunction) {
for (int i = 0; i < 10; i++)
myFunction.accept("hello");
}

有关 Java Lambdas函数式接口的进一步信息

只有一个抽象方法的接口称为泛函接口。 使用@FunctionalInterface 并不是强制性的,但是最佳实践是将它与函数式接口一起使用,以避免意外地添加额外的方法。如果接口使用@FunctionalInterface 注释,并且我们尝试使用多个抽象方法,那么它会抛出编译器错误。

package com.akhi;
@FunctionalInterface
public interface FucnctionalDemo {


void letsDoSomething();
//void letsGo();      //invalid because another abstract method does not allow
public String toString();    // valid because toString from Object
public boolean equals(Object o); //valid


public static int sum(int a,int b)   // valid because method static
{
return a+b;
}
public default int sub(int a,int b)   //valid because method default
{
return a-b;
}
}

功能界面:

  • Java8引入
  • 接口,该接口包含“单个抽象”方法。

例子一:

   interface CalcArea {   // --functional interface
double calcArea(double rad);
}

例二:

interface CalcGeometry { // --functional interface
double calcArea(double rad);
default double calcPeri(double rad) {
return 0.0;
}
}

例三:

interface CalcGeometry {  // -- not functional interface
double calcArea(double rad);
double calcPeri(double rad);
}

Java8注释—— @FunctionalInterface

  • 注释检查接口是否只包含一个抽象方法。如果不包含,则引发错误。
  • 即使@FunctionalInterface 丢失了,它仍然是函数式接口(如果只有一个抽象方法的话)。
  • 函数接口可能有额外的静态和默认方法。
  • 例如,Iterable < > ,compable < > ,Compator < > 。

功能界面的应用:

  • 方法引用
  • Lambda 表达式
  • 构造函数引用

要学习函数接口,首先要学习接口中的默认方法,学习函数接口后,方法引用和 lambda 表达式就容易理解了

函数式接口: 如果一个接口只有一个抽象方法,而不管默认或静态方法的数量是多少,那么这个接口就被称为函数式接口。函数接口用于 Lamda 表达。RunnableCallableComparableComparatorFunctional接口的几个例子。

关键词:

  • 使用注释 @FunctionalInterface(可选)。
  • 它应该只有一个抽象的方法(不管默认和静态的数量 方法)。
  • 两个抽象方法给出了编译错误(Provider@FunctionalInterface注释为 使用)。

这个 线更详细地讨论了函数接口给匿名类带来的好处以及如何使用它们。

完全理解 java 8中的函数式接口

理解函数式接口 | 第一部分 | 什么是函数式接口? : https://youtu.be/u_c5kTteIT4

理解函数式接口 | 第二部分 | 函数式接口语法和示例: https://youtu.be/0rL9ZFAq_rY

理解函数式接口 | 第三部分 | 继承情况下的函数式接口: https://youtu.be/HhKWpZxHWZs

理解函数式接口 | 第四部分 | 调用 Lambda Expression 的函数式接口: https://youtu.be/7tQwXDxUevE

理解函数式接口 | 第五部分 | 调用 Lambda 表达式的函数式接口: https://youtu.be/Ggf091Jnbxw

理解函数式接口 | 第四部分 | 调用 Lambda Expression 的函数式接口: https://youtu.be/Ggf091Jnbxw

理解函数式接口 | 第 VII 部分 | 匿名内部类的 Lambda 表达式: https://youtu.be/HDvUL0frlZo