函数式接口
函数式接口
最近看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实战》书中,把这种函数式接口作为参数传递思想叫做:
行为参数化,就是一个方法接受多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力。