函数式接口

函数式接口 最近看Hutool代码的时候,发现作者源码中使用了很多函数式接口
比如:

	public static <T extends CharSequence, X extends Throwable> T notEmpty(T text, Supplier<X> errorSupplier) throws X {
		if (StrUtil.isEmpty(text)) {
			throw errorSupplier.get();
		}
		return text;
	}

上面的代码如果不用函数式接口应该怎样实现呢

    public static <T extends CharSequence, X extends Throwable> T notEmpty(T text, X errorSupplier) throws X {
        if (StrUtil.isEmpty(text)) {
            throw errorSupplier;
        }
        return text;
    }

对比一下上面两种写法。
咋一看上面两种写法也没有很大区别,但是,如果要在调用notEmpty的时候根据不同的情况返回不同的Throwable,下面的写法必须根据实际情况进行多次调用:

    public static void main(String[] args) {
        boolean check = false;
        notEmpty1("1", () -> {
            if (check) {
                return new IllegalArgumentException("str is null");
            } else {
                return new NullPointerException("str is null");
            }
        });
		//当然,如果只想调用一次,这里也可以另写一个方法,返回一个Throwable,这个后面再讲
        if (check) {
            notEmpty2("1", new IllegalArgumentException("str is null"));
        } else {
            notEmpty2("1", new NullPointerException("str is null"));
        }
    }

捋一捋上面的写法,其实就是给方法体(A方法)传递一个接口,在调用A方法的时候实现B方法,B的调用放在A内部。
函数式接口的好处是什么呢,我的理解就是可以在方法体的形参上写代码块,原本只能传递形参的方法A,升级成了可以传递代码块的“高阶函数”。
再举一个例子
策略模式,根据不同的场景,实现不同的支付方式

public class Test2 {
    public static void main(String[] args) {
		IMyPay wxinPay = new WxinPay();
        IMyPay aliPay = new aliPay();
        wxinPay.pay();
        aliPay.pay();
    }
	
	//支付接口
    public interface IMyPay {
        void pay();
    }
	
	//微信支付
    public static class WxinPay implements IMyPay {
        @Override
        public void pay() {
            System.out.println("微信支付");
        }
    }
	
	//支付宝支付
    public static class aliPay implements IMyPay {
        @Override
        public void pay() {
            System.out.println("支付宝支付");
        }
    }
}

如果用函数式接口,怎样实现呢?

    public static void main(String[] args) {
        pay("微信支付", System.out::println);
        pay("支付宝支付", System.out::println);
    }

    public static void pay(String msg, Consumer consumer) {
        consumer.accept(msg);
    }

因为pay()方法可以传递代码块,也就是Consumer接口,所以替代了上面的策略模式写法。
在《Java8实战》书中,把这种函数式接口作为参数传递思想叫做:
行为参数化,就是一个方法接受多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力。