概念
函数式接口在java中指的是:有且只有一个抽象方法的接口。
@FunctionalInterface注解
java8中专门为函数式接口引入一个新的注解,叫**@FunctionalInterface**,该注解用在接口的定义上
比如:
@FunctionalInterface
public interface Animal {
public abstract void eat();
// public abstract void walk();
}
注意:一旦使用了这个FunctionalInterface注解定义接口,编译器就会检查接口是否有且只有一个抽象方法,没有满足的话就会报错。(但是即使没有使用这个注解,只要接口满足函数接口的要求,仍是一个函数接口,加这个注解只是帮助检查)

关于接口中的static方法和default方法
static方法
java8中接口可以定义一个或多个static方法,使用方法和普通static方法一样。
注意:实现接口的类或者子接口是不会继承接口中的静态方法的。
default方法
java8在接口中新增的default定义方法,default默认方法不是抽象方法,不会影响函数接口的判断。
定义的default方法,子接口或实现类可以不需要实现,直接调用,也可以重写这个default定义的方法(重写时候不需要加default关键字)。
注意:函数式接口中有且只能有一个抽象方法,但可以有多个static方法或default方法。
常用的函数式接口主要在包java.util.function中提供,主要有以下几种常用接口。
Supplier
抽象方法
T get():返回指定泛型的数据
由于Supplier是一个函数式接口,意味着使用Lambda表达式时需要供给一个符合泛型类型的对象数据。
import java.util.function.Supplier;
public class FunctionInterfaceDemo {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Java";
String s = strConcat(()-> str1 + str2);
System.out.println(s);
}
// 拼接字符串
public static String strConcat(Supplier<String> supplier) {
return supplier.get();
}
}
其实就是使用函数式接口作为函数参数,调用时使用Lambda表达式实现函数式接口的抽象方法。
而Supplier的抽象方法get是返回一个泛型类型的数据对象,这里是String,所以返回一个String。
Consumer
抽象方法
void accept(T t):对给定的参数执行此操作(消费数据t)
默认方法
default Consumer:组合消费,先执行调用andThen接口的对象的accept方法,再执行after中的accept方法。
accept()使用实例:
import java.util.function.Consumer;;
public class FunctionInterfaceDemo {
public static void main(String[] args) {
String str = "Hello World";
consumeStr(str, (s) -> System.out.print(s));
}
// 消费字符串
public static void consumeStr(String str, Consumer<String> consumer) {
consumer.accept(str);
}
}
andThen()使用实例:
import java.util.function.Consumer;;
public class FunctionInterfaceDemo {
public static void main(String[] args) {
String str = "Hello World";
consumeStr(str,
(s) -> System.out.println(s.toUpperCase()),
(s) -> System.out.println(s.toLowerCase()));
}
// 消费字符串,先变大写,再变小写
public static void consumeStr(String str, Consumer<String> con1, Consumer<String> con2) {
con1.andThen(con2).accept(str);
}
}
Predicate
抽象方法
boolean Test(T t):传入一个参数,返回一个布尔值
默认方法
default Predicate and(Predicate super T> other) :相当于逻辑运算中的与&&,当两个Predicate函数返回结果都是true时才返回true。default Predicate or(Predicate super T> other) :相当于逻辑运算中的或||,当两个Predicate函数返回结果有一个为true,则返回true,否则返回false。default Predicate negate() :相当于逻辑运算中的!,就是取反的意思。test()实例:
import java.util.function.Predicate;;;
public class FunctionInterfaceDemo {
public static void main(String[] args) {
Predicate<Integer> predicate1 = (t) -> t > 0;
// 执行test方法,会将参数10 进行 t>0 判断,结果返回true
System.out.println(predicate1.test(10));
}
}
and(),or(),negate()实例:
import java.util.function.Predicate;;;
public class FunctionInterfaceDemo {
public static void main(String[] args) {
/**
* 两个条件同时成立:
* 1. 字符串长度大于5
* 2. 以'A'开头
*/
String[] array = {"Hello", "Air", "Apple", "Another"};
Predicate<String> pre1 = (t) -> t.length() > 5;
Predicate<String> pre2 = (t) -> t.startsWith("A");
for (String s : array) {
if(pre1.and(pre2).test(s) == true) {
System.out.println(s);
}
} // 输出Another
System.out.println("---------------");
/**
* 只要有一个条件成立:
* 1. 字符串长度大于5
* 2. 以'A'开头
*/
for (String s : array) {
if(pre1.or(pre2).test(s) == true) {
System.out.println(s);
}
} // 输出Air,Apple,Another
System.out.println("---------------");
/**
* 取反:
* 1. 字符串长度大于5
*/
for (String s : array) {
if(pre1.negate().test(s) == true) {
System.out.println(s);
}
} // 输出Hello,Air,Apple
}
}
Function
该接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
抽象方法
R accept(T t):根据类型T的参数获取参数类型R的结果。
默认方法
default Function andThen(Function super R, ? extends V> after) :组合操作,先执行调用andThen函数的对象的apply方法,然后再执行参数after中的apply方法。default Function compose(Function super V, ? extends T> before) :与andThen相反,先调用before中的apply方法,再调用执行compose方法的对象中的apply方法。import java.util.function.Function;
public class FunctionInterfaceDemo {
public static void main(String[] args) {
Function<Integer, Integer> func = (t) -> t * 2;
System.out.println(func.apply(8)); // 输出 16
System.out.println("------------");
Function<Integer,Integer> fun1 = (t) -> t * t;
Function<Integer,Integer> fun2 = (t) -> t + 2;
// andThen和compose是相反的操作,相同的参数,结果完全不一样
System.out.println(fun1.andThen(fun2).apply(8)); // 输出 66
System.out.println(fun1.compose(fun2).apply(8)); // 输出 100
}
}