Java 8中函数式接口的定义

7

在Java 8中,功能接口的定义如下:

函数式接口被定义为任何具有恰好一个显式声明的抽象方法的接口。(这个限定是必要的,因为接口可能具有非抽象默认方法。)这就是为什么功能接口曾被称为单抽象方法 (SAM) 接口的原因,这个术语有时仍然可以看到。

那么我们为什么会有这样的情况呢:

List<Double> temperature = 
   new ArrayList<Double>(Arrays.asList(new Double[] { 20.0, 22.0, 22.5 }));
temperature.sort((a, b) -> a > b ? -1 : 1);

作为List中的sort方法:
default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }

lambda表达式表示:

Lambda表达式应该可分配给函数接口

Comparator接口有两个抽象方法,即compareequals,并且带有@FunctionalInterface注释。这是否违反了仅具有一个抽象方法的函数接口的定义?


1
Java 中的每个类都继承自 Object 并具有隐式方法 Object::toStringObject::equalsObject::hashCode。因此,Comparator<T> 是一个带有 SAM 的接口,它重写了隐式方法。 - Flown
你从哪里获取了这个定义? - Tunaki
有很多博客,我在那里阅读了我上面分享的定义。根据stackoverflow的指南,我不能分享其他博客的链接。 - Deepak Kumar
2
不要以博客为知识依据。有足够的官方材料可供学习,例如:官方文档1官方文档2官方文档3。你可以使用第三方教程和博客,但如果它们引起困惑,请与官方来源进行核实。 - Holger
1个回答

14

的确,Comparator接口有两个抽象方法。但其中一个是equals,它覆盖了Object类中定义的equals方法,这个方法不算在内。

来自@FunctionalInterface

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

因此,这使得Comparator接口成为一个函数式接口,其中的函数方法是compare(o1, o2)

lambda表达式(a, b) -> a > b ? -1 : 1符合该约定:它声明了两个参数并返回一个int


2
而且如果我们在这方面,应该强调的是,与问题引用中所声称的不同,这个定义并不要求显式声明抽象方法。 - Holger
2
需要提及的是,虽然这个 lambda 表达式符合该函数的形状,因此被编译器接受,但它违反了Comparator接口的契约,可能会在运行时引起任意混乱... - Holger
1
是的,在这种情况下,Comparator.reverseOrder() 是一个更好的选择。 - Tunaki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接