目录
函数式接口
函数式接口(functional interface 也叫功能性接口),简单来说函数式接口就是只包含一个抽象方法的接口,Java标准库中的java.lang.Runnable和java.util.Comparator都是函数式接口。
1.函数式接口定义默认方法
函数式接口里可以包含默认方法,因为默认方法不是抽象方法,其有一个默认实现,所以是函数式接口定义的;
2.函数式接口定义静态方法
函数式接口可以包含静态方法,因为静态方法不能是抽象方法,是一个已经实现了的方法,所以是符合函数式接口定义的;
3.函数式接口定义java.lang.Object里的public方法:
函数式接口里是可以包含Object里的public方法,这些方法对于函数式接口来说,不被当成抽象方法(虽然他们是抽象方法);因为任何一个函数式接口的实现,默认都继承了Object类,包含了来自java.lang.Object里对这些抽象方法的实现;
4.函数式接口里面允许子接口多继承
函数式接口里面允许子接口继承多个父接口,但每个父接口都只能存在一个抽象方法,且必须相同的抽象方法。
- 下面几个为函数式接口的例子:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
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) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
…………
@FunctionalInterface
public interface A<T> extends Predicate, MyPredicate {
/**
* 1.
* 父接口 MyPredicate与 Predicate中存在相同的抽象方法:boolean test(T t);
* 因此子接口中的功能也只有 boolean test(T t);
*/
/**
* 2.
* 如果多个父接口有各自不同的抽象方法,则子接口也会存在继承多个抽象方法
* 此时,子接口就不是函数式接口
*/
}
接口注解
Java8特意为函数式接口提供了一个新的注解@FunctionalInterface,这个注解式非必须的,可以不写,但是如果你的同事在你的类里面添加了一个新的方法那你的接口实现就会报错了,添加上@FunctionalInterface你同事在编译期的时候就会报错误警告,算是一个规范吧。
接口的运用
- 函数式接口也是接口,依旧可以通过之前的调用方式,通过实现类来使用接口。
public class FunctionalInterfaceTest<T> implements Predicate<T>{
public static void main(String[] args) throws InterruptedException {
Predicate p = new FunctionalInterfaceTest();
System.out.println(p.test(1));
}
@Override
public boolean test(T t) {
return 1 % 2 == 0;
}
}
- 也可以通过Lambda表达式来实现抽象方法
public static void main(String[] args) throws InterruptedException {
Predicate<Integer> p = a -> a % 2 == 1;
System.out.println(p.test(5));
System.out.println(p.test(2));
}
- 函数式接口和以前编码的比较
/**
* java 8 之前通常使用匿名内部类完成
*/
Collections.sort(dtoList, new Comparator<PlatformCouponOrderDTO>() {
@Override
public int compare(PlatformCouponOrderDTO a, PlatformCouponOrderDTO b) {
return DateUtils.getMinutesBetween(a.getTime(), b.getTime());
}
});
/**
* java 8 之后使用Lambda表达式实现函数式接口,使代码量明显减少许多
*/
Collections.sort(dtoList, (a, b) -> DateUtils.getMinutesBetween(a.getTime(), b.getTime()));
- 使用函数式接口配合lambda表达式比以前通过内部类的方式实现简便了很多。
public class Demo1 {
public static void main(String[] args) {
runThreadByLambda();
runThreadByInnerClass();
}
public static void runThreadByLambda() {
/*
Runnable就是一个函数式接口:他只有一个方法run()方法。
1、因为run()方法没有参数,所以 ->前面的()中不需要声明形参
2、run返回的是void,所以不需要return。
3、->后面写的代码其实就是定义在run方法内的代码。因为此处代码只有一行,所以{}也可以省略。如果此处多与一行,则无法省略。
*/
Runnable runnable = () -> System.out.println("这个是用拉姆达实现的线程");
new Thread(runnable).start();
}
public static void runThreadByInnerClass() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("这个是用内部类实现的线程");
}
};
new Thread(runnable).start();
}
}
java8新增的函数式接口
- java.util.function
java.util.function 它包含了很多类,用来支持 Java的 函数式编程,该包中的函数式接口有:
序号 | 接口 & 描述 |
---|---|
1 | BiConsumer<T,U> 代表了一个接受两个输入参数的操作,并且不返回任何结果 |
2 | BiFunction<T,U,R>代表了一个接受两个输入参数的方法,并且返回一个结果 |
3 | BinaryOperator<T>代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
4 | BiPredicate<T,U>代表了一个两个参数的boolean值方法 |
5 | BooleanSupplier代表了boolean值结果的提供方 |
6 | Consumer<<T>代表了接受一个输入参数并且无返回的操作 |
7 | DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
8 | DoubleConsumer代表一个接受double值参数的操作,并且不返回结果。 |
9 | DoubleFunction<R>代表接受一个double值参数的方法,并且返回结果 |
10 | DoublePredicate代表一个拥有double值参数的boolean值方法 |
11 | DoubleSupplier代表一个double值结构的提供方 |
12 | DoubleToIntFunction接受一个double类型输入,返回一个int类型结果。 |
13 | DoubleToLongFunction接受一个double类型输入,返回一个long类型结果 |
14 | DoubleUnaryOperator接受一个参数同为类型double,返回值类型也为double 。 |
15 | Function<T,R>接受一个输入参数,返回一个结果。 |
16 | IntBinaryOperator接受两个参数同为类型int,返回值类型也为int 。 |
17 | IntConsumer接受一个int类型的输入参数,无返回值 。 |
18 | IntFunction<R>接受一个int类型输入参数,返回一个结果 。 |
19 | IntPredicate:接受一个int输入参数,返回一个布尔值的结果。 |
20 | IntSupplier无参数,返回一个int类型结果。 |
21 | IntToDoubleFunction接受一个int类型输入,返回一个double类型结果 。 |
22 | IntToLongFunction接受一个int类型输入,返回一个long类型结果。 |
23 | IntUnaryOperator接受一个参数同为类型int,返回值类型也为int 。 |
24 | LongBinaryOperator接受两个参数同为类型long,返回值类型也为long。 |
25 | LongConsumer接受一个long类型的输入参数,无返回值。 |
26 | LongFunction<R>接受一个long类型输入参数,返回一个结果。 |
27 | LongPredicateR接受一个long输入参数,返回一个布尔值类型结果。 |
28 | LongSupplier无参数,返回一个结果long类型的值。 |
29 | LongToDoubleFunction接受一个long类型输入,返回一个double类型结果。 |
30 | LongToIntFunction接受一个long类型输入,返回一个int类型结果。 |
31 | LongUnaryOperator接受一个参数同为类型long,返回值类型也为long。 |
32 | ObjDoubleConsumer<T>接受一个object类型和一个double类型的输入数,无返回值。 |
33 | ObjIntConsumer<T>接受一个object类型和一个int类型的输入参数,无返回值。 |
34 | ObjLongConsumer<T>接受一个object类型和一个long类型的输入参数,无返回值。 |
35 | Predicate<T>接受一个输入参数,返回一个布尔值结果。 |
36 | Supplier<T>无参数,返回一个结果。 |
37 | ToDoubleBiFunction<T,U>接受两个输入参数,返回一个double类型结果 |
38 | ToDoubleFunction<T>接受一个输入参数,返回一个double类型结果 |
39 | ToIntBiFunction<T,U>接受两个输入参数,返回一个int类型结果。 |
40 | ToIntFunction<T>接受一个输入参数,返回一个int类型结果。 |
41 | ToLongBiFunction<T,U>接受两个输入参数,返回一个long类型结果。 |
42 | ToLongFunction<T>接受一个输入参数,返回一个long类型结果。 |
43 | UnaryOperator<T>接受一个参数为类型T,返回值类型也为T。 |