代码重构,为了确保功能的等效性,梳理代码时,发现如下代码:
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 }
View Code
问题:
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 值。包含方法 : |
函数式接口,具体请参考:
简单一句话:只要是@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 }
View Code
解释:
接口有一个 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 }
View Code
结论:
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方法体中的内容...