简介

函数式接口:有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 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供给型函数
  • Consumer消费型函数
  • Runnable无参无返回型函数
  • Function 有参有返回型函数

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;
    }
    
}