78

最近我开始探索 Java 8,我不太了解 Java 实现 lambda 表达式所必需的“函数式接口”的概念。在 Java 中有一个非常全面的 lambda 函数指南,但我卡在了定义函数接口概念的那一章。定义如下:

更准确地说,函数式接口被定义为只有一个抽象方法的任何接口。

然后他继续举例,其中一个是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方法都是抽象的,这意味着它有两个抽象方法那么,如果定义需要一个接口只有一个抽象方法,这怎么能工作呢?我在这里想念什么?

4

8 回答 8

71

From the same page you linked to:

The interface Comparator is functional because although it declares two abstract methods, one of these—equals— has a signature corresponding to a public method in Object. Interfaces always declare abstract methods corresponding to the public methods of Object, but they usually do so implicitly. Whether implicitly or explicitly declared, such methods are excluded from the count.

I can't really say it better.

于 2013-02-01T22:25:14.783 回答
15

@FunctionalInterface 页面中给出了另一种解释:

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

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

例如:

  • 这行得通

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

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

    在接口 FunctionalInterf 中找到多个非覆盖抽象方法

于 2016-02-23T09:54:49.367 回答
3

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

一个。

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

于 2016-02-20T11:10:35.380 回答
1

一个函数式接口只有一个抽象方法,但它可以有多个默认方法和静态方法。

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

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

default void perform1(){
//Method body
}

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

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

Comparator是一个函数式接口,尽管它声明了两个抽象方法。因为这些抽象方法之一“<code>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
    }
于 2020-07-03T12:16:28.867 回答
1

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

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

这是标准的 Java 语言规范,它是这样声明的,

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

这就是在接口中声明 Object 类的方法的方式。根据 JLS,这不算作接口的抽象方法。因此,比较器接口是一个功能接口。

于 2021-05-29T15:08:52.893 回答
-1

Java 文档说:

请注意,不要覆盖 Object.equals(Object) 始终是安全的。但是,在某些情况下,重写此方法可能会通过允许程序确定两个不同的比较器施加相同的顺序来提高性能。

也许比较器很特别?也许,即使它是一个接口,也有某种equals()调用的默认实现compare()?从算法上讲,这是微不足道的。

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

于 2013-02-01T22:19:54.257 回答
-1

定义:

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

用法:

  1. 一旦我们编写了 Lambda 表达式“->”来调用它的功能,那么在这种情况下我们需要功能接口。
  2. 我们可以使用功能接口引用来引用 Lambda 表达式。
  3. 在函数式接口内部,我们可以有一个抽象方法和 n 个默认/静态方法。

关于继承的功能接口:

如果一个接口继承了Functional接口,而子接口不包含任何抽象方法,那么子接口也被认为是Functional Interface。

函数式接口对 java 来说并不新鲜,它已经在以下接口 API 中使用:

  1. Runnable :仅包含 run() 方法。
  2. Callable :仅包含 call() 方法。
  3. Comparable :仅包含 compareTo() 方法。
于 2017-12-06T13:24:55.593 回答
-1

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

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

意思是 -

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

示例代码的更多详细信息https://readtorakesh.com/functional-interface-java8/

于 2018-08-11T17:16:46.147 回答