简介
函数式接口:有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式
一般我们在创建函数式接口时,都会加上@FunctionalInterface
注解,声明这个接口是函数式接口
例如:
@FunctionalInterface
public interface DemoService {
void demo(String msg);
}
在 Java8 之前,我们只能通过匿名内部类进行使用:
DemoService demoService = new DemoService() {
@Override
public void demo(String msg) {
System.out.println(msg);
}
};
demoService.demo("hello, world");
但在 Java8 中,只需要一个 Lambda 表达式就 OK 了
DemoService demoService = msg -> {
System.out.println(msg);
};
demoService.demo("hello, world");
在我们的开发中经常会遇到一些 if…else 的判断来决定是否抛出异常或者进行一些分支操作,这种 if…else 会严重影响代码的美观,所以我们可以用函数式接口优雅的解决这个问题。
在此之前我们需要认识到函数式接口的四种类型:
Supplier 供给型函数:
其表现形式为 不接受参数、只返回数据
// 表示结果的供应商。
// 不要求每次调用供应商时都返回新的或不同的结果。
// 这是一个函数接口,其函数方法是get()。
// 自:
// 1.8
// 类型形参:
// <T> –该供应商提供的结果类型
@FunctionalInterface
public interface Supplier<T> {
/**
* 返回一个结果
*
* @return a result
*/
T get();
}
Consumer 消费型函数
其表现形式为 接收一个参数,没有返回值
// 表示接受单个输入参数但不返回结果的操作。与大多数其他功能接口不同,
// 预计Consumer会通过副作用进行操作。
// 这是一个函数接口,其函数方法为accept(Object)
// <T> –该供应商提供的结果类型
@FunctionalInterface
public interface Consumer<T> {
/**
* 对给定的参数执行此操作
*
* @param 入参
*/
void accept(T t);
/**
* 返回一个组合的Consumer,该Consumer依次执行此操作和after操作。
* 如果执行任何一个操作都会引发异常,则会将异常中继到组合操作的调用方。
* 如果执行此操作会引发异常,则不会执行after操作。
*
* @param 此操作之后要执行的操作
* @return 按顺序执行此操作,然后执行后续操作的组合使用者
*
* @throws 抛出 NullPointerException,如果after为null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
Runnable 无参无返回型函数
// 表示不返回结果的操作。
// 这是一个函数接口,其函数方法是run()
@FunctionalInterface
public interface Runnable {
/**
* 运行此操作
*/
void run();
}
Function 有参有返回型函数
// 表示接受一个参数并生成结果的函数。
// 这是一个函数接口,其函数方法为application(Object)
// <T> –函数输入的类型<R>–函数结果的类型
@FunctionalInterface
public interface Function<T, R> {
/**
* 将此函数应用于给定的参数
*
* @param 函数参数
* @return 返回结果
*/
R apply(T t);
/**
* 返回一个组合函数,该函数首先将before函数应用于其输入,然后将此函数应用于结果。
* 如果对其中一个函数的求值引发异常,则会将其中继到组合函数的调用方。
*
* @param before–应用此函数之前要应用的函数
* @return 先应用before函数,然后应用此函数的组合函数
* @throws 抛出 NullPointerException 如果before为null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* 返回一个组合函数,该函数首先将此函数应用于其输入,然后将after函数应用于结果。
* 如果对其中一个函数的求值引发异常,则会将其中继到组合函数的调用方。
*
* @param <V> after–应用此函数后要应用的函数
* @return 先应用此函数,然后应用after函数的组合函数
* @throws抛出 NullPointerException 如果after为null
*
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* 返回一个始终返回其输入参数的函数
*
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}
函数式接口工具类
@NoArgsConstructor
public class Assert {
/**
* 当给定的expression为true时,抛出异常
* @param expression true或false
* @param errorMsg 要抛出的异常信息
* @throws BusinessException 抛出的异常
*/
public static void isTrue(boolean expression, String errorMsg) throws BusinessException {
if (expression) {
throw new BusinessException(errorMsg);
}
}
/**
* 当给定的expression为true时,执行代码并返回数据
* @param expression true或false
* @param supplier <p> 不接受参数、只返回数据 </p>
* @param <T> 返回的数据类型
* @return 返回的数据,当expression为false时,则返回null
*/
public static <T> T isTrue(boolean expression, Supplier<T> supplier) {
if (expression) {
return supplier.get();
}
return null;
}
/**
* 给定的expression为true时,接收参数并执行代码
* @param expression true或false
* @param args 传入的参数
* @param consumer <p> 接收一个参数,没有返回值 </p>
* @param <T> 传入的参数类型
*/
public static <T> void isTrue(boolean expression, T args, Consumer<T> consumer) {
if (expression) {
consumer.accept(args);
}
}
/**
* 给定的expression为true时,执行代码
* @param expression true或false
* @param runnable <p> 无参无返回 </p>
*/
public static void isTrue(boolean expression, Runnable runnable) {
if (expression) {
runnable.run();
}
}
/**
* 给定的expression为true时,接收参数执行代码后返回结果
* @param expression true或false
* @param args 传入的参数
* @param function <p> 接收一个参数,并返回一个值 </p>
* @param <T> 传入的参数类型
* @param <R> 返回的参数类型
* @return 返回的数据
*/
public static <T, R> R isTrue(boolean expression, T args, Function<T, R> function) {
if (expression) {
return function.apply(args);
}
return null;
}
}