一.语法
基本语法:(parameters)->expression或者(parameters)->{statements;}
parameters:类似方法中的形参列表,这里的参数是函数式接口里面的参数。这里的参数可以明确说明,也可以不声明而由JVM隐含的推断。当只有一个推断类型是可以省略圆括号
->可以理解为被用于
方法体:可以是表达式,也可以是代码块,是函数时接口里方法的实现
举例
()->2 不需要参数,返回值是2;
x->3*x 只需要一个参数,返回该参数的二倍;
(x,y)->x+y 需要两个参数,返回他们的和;
(int x,int y)->x*y 两个参数,返回他们的乘积;
(String s)->System.out.println(s) 接收一个String对象并打印
二.函数式接口
1.定义
如果一个接口只有一个抽象方法,那么这个接口就是一个函数式接口
2.@FunctionalInterface注解
用了这个注解,就表示该接口是一个函数式接口,只能写一个抽象方法,如果多写了一个,就会报错。
3.可以有其他非抽象的方法
三.Lambda表达式的基本用法
首先准备以下六个函数式接口
如果没有Lambda表达式,应该如下调用:用到了匿名内部类,重写了test方法,如下:
以上六种函数式接口使用Lambda表达式如下:
注意,以上所有return语句的return###都可以直接如下写法:
四.变量的捕获
Lambda表达式当中存在变量的捕获,我们先通过匿名内部类来了解变量的捕获:
如上可以正常输出,但下面的代码就报错啦:
这是因为,所捕获的变量,要么是被final修饰,要么就得保证在使用之前没有被修改过,所以如下代码也会报错:
在Lambda表达式中也可以进行变量的捕获
同理,只可以是final修饰的常量或者从未修改过的变量
五.Lambda表达式在集合当中的使用
1.Collection接口,forEach()方法
该方法在Iterable接口中
它的参数是Consumer类型的,即实现了Consumer接口的一个对象,该Consumer接口就是一个函数式接口,它里面只有一个抽象方法accept方法:
那么我们该如何使用foreach方法呢?先看一下源码:
源码中将list中的元素依次传向了抽象方法accept,如果我们想打印list中的对象,就要如下使用Lambda表达式:
其中list.forEach((String s)-> System.out.println(s));表示要调用forEach方法,调用时传入一个实现了Consumer接口的对象,其中这个Consumer接口是一个函数式接口,有一个抽象方法accept,它只有一个参数String类型,无返回值。(String s)-> System.out.println(s)表示要对于传入的这个参数进行打印处理。
这个Lambda表达式就等价于:
2.sort()方法
还是像上面的分析方法,它传入了一个实现了Comparator接口的对象,它也是一个函数式接口,只有一个抽象方法compare,所以使用方法如下:
等价于:
3.Map接口,forEach()方法
先看源码:
参数是实现了BiConsumer接口的一个对象,这也是一个函数式接口:
要重写accept方法:
总之,Lambda表达式使得代码更加简洁,但是却是得代码的可读性变差了。