Spring8中lambda表达式的学习(Function接口、BiFunction接口、Consumer接口)
代码重构,为了确保功能的等效性,梳理代码时,发现如下代码:
1 public SingleRespTTO fundI(SingleReqTTO request) throws Exception { 2 return handlerSingleReq((req, logInfo) -> { 3 4 // 业务操作 5 ....略.... 6 }, request); 7 } 8 9 public SingleRespTTO handlerSingleReq(BiConsumer<SingleReqTTO, SingleRespTTO> consumer, 10 SingleReqTTO request) throws Exception { 11 // 业务操作 12 consumer.accept(request, respTTO); 13 ....略.... 14 return respTTO; 15 }
问题:
fundI(SingleReqTTO request)方法实现很简单:
直接调用handlerSingleReq(BiConsumer<SingleReqTTO, SingleRespTTO> consumer,SingleReqTTO request)方法并返回,而handlerSingleReq的参数1 consumer是个lambda表达式:
(req, logInfo) -> {
// 业务操作
....略....
}
1、lambda表达式的方法参数是啥
这个lambda表达式有2个参数:req, logInfo,这是哪来的?
2、方法执行顺序是啥
lambda作为参数,包含有方法体(很明显还是个内部实现),先执行该lambda的内部逻辑呢还是先执行的handlerSingleReq方法体呢?
解析:
lambda的三个概念:Function接口、BiFunction接口、Consumer接口分析
问题答案:
Java8 内置的四大核心函数式接口:
函数式接口 |
参数类型 | 返回类型 | 用途 |
Consumer<T> |
T |
void |
对类型为T的对象应用操作,包含方法 : |
Supplier<T> |
无 | T |
返回类型为T的对象,包含方法 : |
Function<T, R> |
T | R |
对类型为T的对象应用操作,并返回结果。结果是R类型的对象,包含方法 : |
Predicate<T> |
T | Boolean |
确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法 : |
函数式接口,具体请参考:
https://blog.csdn.net/chenshun123/article/details/78122467
https://www.cnblogs.com/knowledgesea/p/3163725.html
https://blog.csdn.net/qq_28410283/article/details/80618456
https://blog.csdn.net/qq_29848473/article/details/79554472
简单一句话:只要是@FunctionalInterface 修饰的接口都是函数式接口,就可以通过lambda表达式简化代码(lambda最大的优势就是简洁的代码)
查看代码,这里调用的是,查看源码如下:
1 @FunctionalInterface 2 public interface BiConsumer<T, U> { 3 4 /** 5 * Performs this operation on the given arguments. 6 * 7 * @param t the first input argument 8 * @param u the second input argument 9 */ 10 void accept(T t, U u); 11 12 /** 13 * Returns a composed {@code BiConsumer} that performs, in sequence, this 14 * operation followed by the {@code after} operation. If performing either 15 * operation throws an exception, it is relayed to the caller of the 16 * composed operation. If performing this operation throws an exception, 17 * the {@code after} operation will not be performed. 18 * 19 * @param after the operation to perform after this operation 20 * @return a composed {@code BiConsumer} that performs in sequence this 21 * operation followed by the {@code after} operation 22 * @throws NullPointerException if {@code after} is null 23 */ 24 default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) { 25 Objects.requireNonNull(after); 26 27 return (l, r) -> { 28 accept(l, r); 29 after.accept(l, r); 30 }; 31 } 32 }
解释:
接口有一个 accept方法,必须自己实现,它接收两个泛型参数,而另一个方法是默认实现好的方法;
简单测试下:
1 public static void main(String[] args) { 2 BiConsumer<Integer,String> biconsumer = (x,y) -> { 3 int a = x + 2; 4 System.out.println(a);// 12 5 System.out.println("----"+y);// ----我爱你 6 }; 7 biconsumer.accept(10,"我爱你"); 8 9 System.out.println("-----执行andThen()方法--------"); 10 BiConsumer<Integer,String> afterBiconsumer = (x,y) -> { 11 int a = x + 8; 12 System.out.println(a);// 18 13 System.out.println("----"+y);// ----哇呀呀 14 }; 15 biconsumer.andThen(afterBiconsumer).accept(10,"哇呀呀"); 16 } 17 }
结论:
BiFunction接口暴露的accept方法必须实现,并且是执行的入口(默认实现的andThen()方法,如果调用会执行两次accept方法,首先执行accept方法,然后执行传入的BiConsumer引用对象的accept方法方法)
lambda表达式中,BiFunction接口实现体自己不会去执行,它只是实现了accept方法,只有手工去调用它的时候才会执行accept方法体的内容。。。
而且,它接受的2个参数,是调用的时候传递过去的,方法体中只是声明为泛型。。。
一切都明了:
1、lambda方法参数是啥
handlerSingleReq方法中,consumer.accept(request, respTTO)调用了lambda的的accept方法,参数就在这传递
2、方法执行顺序是啥
只有调用的时候才执行,handlerSingleReq方法顺序执行,consumer.accept(request, respTTO)时执行lambda方法体中的内容...