函数式接口,是JDK8新进入的新特性。
概念:有且只有一个抽象实例方法(Abstract Method)的接口称为函数式接口(Functional Interface)。但是从Object类里面重写的抽象方法除外。此外为了兼容性,JDK8里面还加入了一个默认方法(default method)在接口里面,默认方法是有具体的实现的。没错,就是接口里面的实现方法。
举例:我们看一下我们都比较熟悉的Comparator接口,这个接口在jdk1.2里面就有了。从jdk8开始这个接口被修改成了函数式接口,我们可以看到在类的声明处加入了@FunctionalInterface的注解。说明这个接口被标记成了函数式接口。
数一下,这个接口目前有18个方法。除了从object类里面继承过来的equals抽象方法外,只有一个compare抽象方法。符合函数式接口的定义。
此外,我们看到了好多default 标记的带有实现的方法。还有好多静态方法。
默认方法(default method):是public的非抽象的实例方法,定义在接口里面。实例方法也就是说不是静态的。
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}
注:函数式接口(Functional Method)是可以使用lambda表达式、方法引用、构造方法引用来进行创建的。
比如上一讲里的Runnable接口我们就是用lambda接口来创建的。方法引用、构造方法引用后续再讲。
在Java里面一个函数式接口,都是用注解 @FunctionalInterface 来进行标注的。并且这个注解只能标注接口,而不能标注注解、class、枚举(enum)。同时这个别标注的接口也必须符合Java对于函数式接口的定义(只有一个抽象方法)。
@FunctionalInterface的源码。可以看出是从jdk8开始加入的。
package java.lang;
import java.lang.annotation.*;
/**
* @jls 4.3.2. The Class Object
* @jls 9.8 Functional Interfaces
* @jls 9.4.3 Interface Method Body
* @jls 9.6.4.9 @FunctionalInterface
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
就说到这里吧,后续再从大量的实例中来展开细说。