lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。
lambda表达式的形式
(参数)->表达式
举例如下
(String first,String second)->first.length()-second.length()
如果代码要完成的计算无法放在一个表达式中,可以用{}把这些计算括起来,如下
(String first,String second) ->
{
if(first.length() < second.length()) return -1;
else if (first.length() > second.length() return 1;
else return 0;)
}
lambda表达式的特点
- 一个 Lambda 表达式可以有零个或多个参数
- 参数的类型既可以明确声明,也可以根据上下文来推断
- 所有参数需包含在圆括号内,参数之间用逗号相隔
- 空圆括号代表参数集为空
- 当只有一个参数,且其类型可推导时,圆括号()可省略
- Lambda 表达式的主体可包含零条或多条语句
- 如果 Lambda 表达式的主体只有一条语句,花括号{}可省略
- 如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)
函数式接口
只有一个抽象方法的接口称为函数式接口。当需要这种接口的对象时,就可以提供一个lambda表达式。
//不使用lambda表达式:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello from thread");
}
}).start();
//使用lambda表达式:
new Thread(
() -> System.out.println("Hello from thread")
).start();
方法引用
方法引用存在两种情况,一种是方法引用等价于提供方法参数的lambda表达式,如
System.out::println
等价于
x->System.out.println(x)
而
Math::pow
等价于
(x,y) -> Math.pow(x,y)
第二种情况是第一个参数会成为方法的目标,如
String::compareToIgnoreCase
等价于
(x,y) -> x.compareToIgnoreCase(y)
变量作用域
lambda表达式有3个部分:
- 一个代码块
- 参数
- 自由变量的值(非参数且不在代码中定义的变量)
举例如下
public static void repeatMessage(String text, int delay)
{
ActionListener listener = event ->
{
System.out.println(text); //lambda表达式捕获自由变量text
Toolkit.getDefaultToolkit().beep();
};
new Timer(delay,listener).start();
}
lambda表达式可以捕获外围作用域中变量的值,但是必须要确保所捕获的值是明确定义的,即只能引用值不会改变的变量。如下例所示,下面的做法是错误的。
public static void countDown(int start, int delay)
{
ActionListener listener = event ->
{
start--; //ERROR,start的值是变化的
System.out.println(start);
};
new Timer(delay,listener).start()
}