Functional 为 lambda 方法提供一个接口
函数式接口
Functional 的定义其实很简单:任何接口,如果只包含 唯一一个抽象方法,那么它就是一个 Functional Interface ,
函数式接口?这注解名字好。
为了让编译器帮助我们确保一个接口满足 Functional Interface 的要求(也就是说有且仅有一个抽象方法),Java8提供了@FunctionalInterface
注解。
先学习函数式接,才能理解学习 Lambda
表达式。
有什么用
白话:用来为函数式编程提供接口。
就是一个有且仅有
一个抽象方法,但是可以有多个非抽象方法
的接口。
函数式接口可以被隐式转换为 lambda 表达式。
简单示例
写一个最简单的例子做为入门参考,看不懂不要紧,这个只是一个例子。
声明一个无参的接口
声明一个无参函数式接口,为 lambda 提供一个接口。
在接口上添加@Functional
那么这个接口就是一个函数式接口
1 2 3 4
| @FunctionalInterface public interfaceMyFunctional { public abstract void run (); }
|
实现接口
自己实现一个Functional
接口,只需要 ()-> System.out.println("test")
进行实现。()->System.out.println("test")
就是一个lambda
实现。
这里主要关注Functional
接口,不需要关注lambda
。
1 2 3 4 5 6 7 8
| public class Test { public static void main(String[] args) { MyFunctional myFunctional = () -> System.out.println("test"); System.out.println(myFunctional.run()); } }
|
使用规则
首先它是一个接口。然后这个接口里面只能有一个抽象方法。
这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。
规则
- 函数式接口里允许定义默认方法,因为默认方法不是抽象方法,其有一个默认实现,所以是符合函数式接口的定义的
- 函数式接口里允许定义静态方法,因为静态方法不能是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义的
- 函数式接口里允许定义Java.lang.Object里的public方法,这些方法对于函数式接口来说,不被当成是抽象方法(虽然它们是抽象方法);因为任何一个函数式接口的实现,默认都继承了Object类,包含了来自
java.lang.Object
里对这些抽象方法的实现;
- 函数式接口里允许子接口继承多个父接口,但每个父接口中都只能存在一个抽象方,且必须的相同的抽象方法。
jdk 中的 lambda 实现示例
使用 Arrays 对数据进行排序。
Arrays 的 sort 方法,可以使用 lambda 的方法,这个方法是怎么实现的呢。
老套路:
- 定义 Functional 接口
- Functional 做为形参
- 有一个地方实现了这个Functional接口
- 调用
1 2 3 4 5 6
| Comparator<String> sortByName = (s1, s2) -> (s1.compareTo(s2)); Arrays.sort(players, sortByName);
Arrays.sort(players, (s1, s2)-> (s1.compareTo(s2)));
|
看看 sort
的具体实现,sort
是对 Comparator
接口的具体实现。
1 2 3 4 5 6 7 8 9 10
| public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } }
|
Comparator
接口
1 2 3 4
| @FunctionalInterface public interface Comparator<T> { ... }
|
默认方法 和 静态方法
默认方法是可以直接被 类名.方法名使用的。
lambda 的默认实现方法,可以直接写在接口当中,然后具体使用的时候引用即可。
封装的时候也可以直接引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import java.util.Objects; import java.util.function.Predicate;
@FunctionalInterface public interface MyFunctional<T> { boolean test(T t); static <T> boolean getBoolean (T b) { System.out.println(b.toString()); return true; } default String testPrintString (String message) { System.out.println(message); return message; } default <T> boolean testPrint (T message) { System.out.println(message); return true; } default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); }
default Predicate<T> negate() { return (t) -> !test(t); }
default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } static <T> Predicate<T> isEqual(Object targetRef) { System.out.println("使用静态方法"); return (null == targetRef)? Objects::isNull: object -> targetRef.equals(object); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void testStaticMethod() { static <T > boolean getBoolean (T b) MyFunctional myFunctional = MyFunctional::getBoolean; myFunctional.test(new Date()); myFunctional.testPrintString("test...."); myFunctional.testPrint(new Date()); testDefault(MyFunctional::getBoolean); MyFunctional.isEqual(new Date()); }
public static String testDefault(MyFunctional myFunctional) { return myFunctional.testPrintString("just test lambda"); }
|