Java 8中的Functional Interface有什么用?

Mad*_*dan 144 java lambda interface java-8

我在Java 8中遇到了一个名为Functional Interface的新术语.

在使用lambda表达式时,我只能找到一个使用此接口的方法.

Java 8提供了一些内置的功能接口,如果我们想要定义任何功能接口,那么我们就可以使用@FunctionalInterface注释.它允许我们在接口中只声明一个方法.

例如:

@FunctionalInterface
interface MathOperation {
    int operation(int a, int b);
}
Run Code Online (Sandbox Code Playgroud)

除了使用lambda表达式之外,它在Java 8中有多大用处?

这里的问题与我提出的问题不同.在使用Lambda表达式时,它询问为什么我们需要功能接口.我的问题是:为什么使用功能接口而不是直接使用lambda表达式

Ser*_*hyr 124

@FunctionalInterface注释对于代码的编译时间检查很有用.除此之外static,您不能使用多个方法,default并且Object在您@FunctionalInterface或任何其他用作功能接口的接口中覆盖方法的抽象方法.

但是你可以在没有这个注释的情况下使用lambdas,也可以覆盖没有@Override注释的方法.

来自docs

功能界面只有一个抽象方法.由于默认方法具有实现,因此它们不是抽象的.如果接口声明了一个覆盖java.lang.Object的公共方法之一的抽象方法,那么它也不会计入接口的抽象方法计数,因为接口的任何实现都将具有java.lang.Object或其他地方的实现.

可以在lambda表达式中使用:

public interface Foo {
  public void doSomething();
}
Run Code Online (Sandbox Code Playgroud)

不能在lambda表达式中使用:

public interface Foo {
  public void doSomething();
  public void doSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)

但这会产生编译错误:

@FunctionalInterface
public interface Foo {
  public void doSomething();
  public void doSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)

"@FunctionalInterface"注释无效; Foo不是一个功能界面

  • 更确切地说,你必须有*一个*抽象方法,它不会覆盖功能接口中`java.lang.Object`中的方法. (37认同)
  • ......除了"静态"和"默认"之外,它与"没有多个`public`方法"略有不同...... (8认同)
  • 仍然不明白拥有它的任何意义。为什么地球上的任何人都会费心检查他/她的接口有多少方法。标记接口仍然有一个点和一个特定的目的。文档和答案仅解释了它的作用,而根本没有解释它的用途。而“使用”正是 OP 所要求的。所以我不推荐这个答案。 (4认同)
  • 这展示了如何使用它们,但没有解释为什么我们需要它们。 (2认同)

Hol*_*ger 12

文件使得的确目的之间的差异

一种信息性注释类型,用于指示接口类型声明旨在成为Java语言规范定义的功能接口.

和用例

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

其措辞并不排除其他一般用例.由于主要目的是指示功能接口,因此您的实际问题归结为" 除了lambda表达式和方法/构造函数引用之外还有其他功能接口用例吗?"

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

JLS§9.8.功能接口:

...

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

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

所以在一句话中,不,Java 8中没有其他用例.


Sin*_*ani 12

正如其他人所说,功能界面是暴露一种方法的界面.它可能有多个方法,但所有其他方法必须具有默认实现.它被称为"功能界面"的原因是因为它有效地充当了一种功能.由于您可以将接口作为参数传递,这意味着函数现在就像函数式编程语言中的"一等公民"一样.这有很多好处,使用Stream API时你会发现它们很多.当然,lambda表达式对它们来说是主要的明显用途.


Lou*_*man 10

一点也不.Lambda表达式是该注释的唯一点.

  • 好吧,lamdbas也没有注释.这是一个断言,就像`@Override`让编译器知道你打算编写一些"功能"的东西(如果你滑倒就会得到一个错误). (6认同)
  • 开门见山,给出正确答案,虽然有点短。我花时间添加了一个[更详细的答案](http://stackoverflow.com/a/36884458/2711488)用更多的词来表达同样的事情...... (2认同)

Han*_*k D 5

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

关于具体的功能接口的好处之一java.util.function是,他们可以组合起来创造新的功能(如Function.andThenFunction.compose,Predicate.and等),由于它们所包含的得心应手默认的方法.


Akh*_*esh 5

只有一种抽象方法的接口称为功能接口。使用@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;
        }
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

功能接口:

  • Java 8 中引入
  • 包含“单一抽象”方法的接口。

示例1:

   interface CalcArea {   // --functional interface
        double calcArea(double rad);
    }           
Run Code Online (Sandbox Code Playgroud)

示例2:

interface CalcGeometry { // --functional interface
    double calcArea(double rad);
    default double calcPeri(double rad) {
        return 0.0;
    }
}       
Run Code Online (Sandbox Code Playgroud)

示例3:

interface CalcGeometry {  // -- not functional interface
    double calcArea(double rad);
    double calcPeri(double rad);
}   
Run Code Online (Sandbox Code Playgroud)

Java8注解——@FunctionalInterface

  • 注解检查接口仅包含一个抽象方法。如果不是,则引发错误。
  • 即使 @FunctionalInterface 缺失,它仍然是函数式接口(如果有单个抽象方法)。注释有助于避免错误。
  • 函数式接口可能有额外的静态和默认方法。
  • 例如,Iterable<>、Comparable<>、Comparator<>。

函数式接口的应用:

  • 方法参考
  • 拉姆达表达式
  • 构造函数参考

学习函数式接口,先学习接口中的默认方法,学习函数式接口后,你会很容易理解方法引用和lambda表达式