一、概述
1. lambda表达式:是一个可传递的代码块, 可以在以后执行一次或多次。
2. lambda命名来源:逻辑学家 Alonzo Church使用小写的希腊字母 λ(lambda )来标记参数,从那以后带参数变量的表达式就被称为 lambda 表达式。
3. lambda语法:
3.1 常规的调用:不能直接传递代码块给caller处理,需要构造包含某种方法的对象来间接传递此代码块,在Java8后也设计了一种可以直接将代码块传递给caller的方式就是Lambda表达式;
//Comparator<String>的实现类LengthComparator(看成一个代码块)
class LengthComparator implements Comparator<String>
{
public int compare(String first, String second)
{
return first.length() - second.length();
}
}
//当sort需要调用上面的接口代码块,常规做法是传递进来其实例化对象;
Arrays.sort(strings, new LengthComparator());
3.2 Lambda表达式格式:参数 -> 表达式
//格式:参数 -> 表达式
(String first,String second) -> first.length() - second.length()
//如果编译器根据上下文可以推导出一个lambda表达式的参数类型,则可以忽略不写其类型
Comparator<String> comp = (first, second) -> first.length() - second.length();
//如果方法只有一个参数, 而且这个参数的类型可以推导得出,那么还可以省略小括号()
Comparator<String> comp = first -> first.length();
//无参数必须要用()空括号,有多个语句要放进一个表达式中用{}约束,也可以在里面使用return语句(跟写方法一样)
() -> {for(int i=0;i<20;i--) System.out.println(i);}
//实际应用:也可以直接将lambda表达式写进去作为接口传递
Arrays.sort(strings, (first, second) -> first.length() - second .length());
Arrays.sort(strings, comp);
二、 函数式接口(functional interface )
1. 概念 :一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
2. 作用:函数式接口可以被隐式转换为 lambda 表达式,那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的)。
3. 注意:
实际上在 Java 中, 对 lambda 表达式所能做的也只是能转换为函数式接口;
lambda表达式不可以赋值给 非函数式接口类型变量,比如Object类型变量;
4. 示例:
在这里插入代码片
三、方法引用
格式: 用:: 操作符分隔方法名与对象或类名,有下面3种情况;
1.引用对象的方法 object::instanceMethod
//out是一个PrintStream打印流对象,println是其一个打印方法
System.out::println 等价于 x -> System.out.println(x)
2.引用静态方法 Class::staticMethod
//pow()方法是Math类的静态方法,类可以直接调用
Math::pow 等价于(x,y) -> Math.pow(x, y)
3.引用容器中对象的方法 Class::instanceMethod
//toLowerCase()是String类中的转小写方法
String::toLowerCase 等价于 s -> s.toLowerCase()
四、构造器引用
1.格式:构造器引用与方法引用很类似,只不过方法名为 new;
//Person无参构造器的引用
Person::new 等价于 () -> new Person()
//int[] 数组构造器的引用,初始一个长度为x的参数
int[]::new 等价于 x -> new int[x]
2.注意:
Java 有一个限制,无法构造泛型类型 T 的数组;
五、变量作用域
在 lambda 表达式中访问外围方法或类中的变量
lambda 表达式可以捕获外围作用域中变量的值。在 Java 中,要确保所捕获的值是明确定义的,这里有一个重要的限制。在 lambda 表达式中, 只能引用值不会改变的变量;