Java 8中“功能接口”的精确定义

时间:2013-02-01 22:12:49

标签: lambda java-8 abstract functional-interface

最近我开始探索Java 8,我无法理解“功能接口”的概念,这对Java实现lambda表达式至关重要。在Java中有一个pretty comprehensive guide到lambda函数,但我被卡在the chapter that gives definition to the concept of functional interfaces上。定义如下:

  

更确切地说,功能接口被定义为具有一个抽象方法的任何接口。

然后他进入示例,其中一个是Comparator接口:

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
} 

我能够测试我可以使用lambda函数代替Comparator参数并且它可以工作(即Collections.sort(list, (a, b) -> a-b))。

但是在Comparator界面中,compareequals方法都是抽象的,这意味着它有两个抽象方法。那么如果定义要求接口具有恰好一个抽象方法,那么它如何工作?我在这里缺少什么?

8 个答案:

答案 0 :(得分:55)

来自same page you linked to

  

接口Comparator是有用的,因为虽然它声明了两个抽象方法,但其中一个 - equals-具有与Object中的公共方法相对应的签名。接口总是声明对应于Object的公共方法的抽象方法,但它们通常是隐式的。无论是隐式声明还是显式声明,此类方法都会从计数中排除。

我真的不能说得更好。

修改:根据Maurice的评论(感谢!)更新到此页面的最新文本

答案 1 :(得分:7)

另一种解释在@FunctionalInterface page

中给出
  

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

您可以使用 @FunctionalInterface 测试哪个界面是正确的功能界面

E.g:

  • 这项工作

    @FunctionalInterface
    public interface FunctionalInterf {
    
        void m();
    
        boolean equals(Object o);
    
    }
    
  • 这会产生错误:

    @FunctionalInterface
    public interface FunctionalInterf {
    
        void m();
    
        boolean equals();
    
    }
    
      

    在FunctionalInterf接口

    中找到多个非重写抽象方法

答案 2 :(得分:3)

Q值。但是在Comparator接口中,compare()和equals()方法都是抽象的,这意味着它有两个抽象方法。那么如果定义要求接口只有一个抽象方法,那么它如何工作呢?我在这里缺少什么?

一个。

  

功能接口可以指定Object定义的任何公共方法,例如equals(),   而不影响其“功能接口”状态。公共Object方法被认为是隐式的   功能接口的成员,因为它们是由a的实例自动实现的   功能界面。

答案 3 :(得分:0)

Java文档说:

  

请注意,不要覆盖Object.equals(Object)总是安全的。   但是,在某些情况下,覆盖此方法可能会有所改善   通过允许程序确定两个不同的性能   比较器强制执行相同的命令。

也许Comparator很特别?也许,即使它是一个接口,也有某种调用equals()的{​​{1}}默认实现?从算法上讲,它是微不足道的。

我认为在接口中声明的所有方法都是抽象的(即没有默认实现)。但也许我错过了一些东西。

答案 4 :(得分:0)

<强>定义:

如果一个接口只包含一个抽象方法,那么这种类型的接口称为功能接口。

<强>用法:

  1. 一旦我们写了Lambda表达式“ - &gt;”调用它的功能, 那么在这种情况下我们需要功能界面。
  2. 我们可以使用功能接口参考来引用Lambda 表达
  3. 在功能界面内,我们可以有一个抽象方法和n 默认/静态方法的数量。
  4. 关于继承的功能界面:

    如果接口扩展了Functional接口且子接口不包含任何抽象方法,则子接口也被视为功能接口。

    功能界面对于java来说并不陌生,它已在以下接口API中使用:

    1. Runnable:仅包含run()方法。
    2. Callable:仅包含call()方法。
    3. Comparable:仅包含compareTo()方法。

答案 5 :(得分:0)

在Java 8之前,接口只能声明一个或多个方法,也称为抽象方法(没有实现的方法,只有签名)。从Java 8开始,接口还可以实现一个或多个方法(称为接口默认方法)和静态方法以及抽象方法的实现。界面默认方法标记为默认关键字。

问题是,什么是功能接口? 具有单一抽象方法(SAM)的接口称为功能接口。

意思是-

  1. 具有单一抽象方法的接口是功能接口
  2. 具有单一抽象方法且零个或多个默认值的接口 方法和零个或多个静态方法也是有效的 界面。

使用示例代码https://readtorakesh.blogspot.com/2018/08/functional-interface-java8.html

的更多详细信息

答案 6 :(得分:0)

功能界面只有一种抽象方法,但可以具有多个默认和静态方法。

由于默认方法不是抽象的,因此您可以随意在功能接口中添加任意数量的默认方法。

@FunctionalInterface
public interface MyFuctionalInterface 
{
public void perform();

default void perform1(){
//Method body
}

default void perform2(){
//Method body
}
}

如果接口声明的抽象方法覆盖java.lang.Object的公共方法之一,则该方法也不计入接口的抽象方法计数,因为该接口的任何实现都将具有java.lang.Object的实现或其他地方。

比较器是一个功能接口,即使它声明了两个抽象方法。因为这些抽象方法之一“ equals()”的签名等于Object类中的公共方法。 例如界面下方是有效的功能界面。

@FunctionalInterface
    public interface MyFuctionalInterface 
    {
    public void perform();
 
    @Override
    public String toString();                //Overridden from Object class
 
    @Override
    public boolean equals(Object obj);        //Overridden from Object class
    }

答案 7 :(得分:0)

接口不能扩展对象类,因为接口必须有公共和抽象方法。

对于 Object 类中的每个公共方法,接口中都有一个隐式的公共和抽象方法。

这是标准的 Java 语言规范,声明如下,

<块引用>

“如果一个接口没有直接的超接口,那么接口隐式声明一个公共抽象成员方法m,签名为s,返回类型r,并抛出子句t对应每个签名为s的公共实例方法m,返回类型为r , 和在 Object 中声明的 throws 子句 t ,除非接口显式声明了具有相同签名、相同返回类型和兼容的 throws 子句的方法。”

这就是在接口中声明 Object 类的方法的方式。根据 JLS,这不算作接口的抽象方法。因此,Comparator 接口是一个函数式接口。