lambda写的好可以极大的减少代码冗余,同时可读性也好过冗长的内部类,匿名类。
先列举两个常见的简化(简单的代码同样好理解)
lambda表达式配合Java8新特性Stream API可以将业务功能通过函数式编程简洁的实现。(为后面的例子做铺垫)
例如:
这段代码就是对一个字符串的列表,把其中包含的每个字符串都转换成全小写的字符串。注意代码第四行的map方法调用,这里map方法就是接受了一个lambda表达式。
(Type1 param1, Type2 param2, ..., TypeN paramN) -> { statment1; statment2; //............. return statmentM; }
这是lambda表达式的完全式语法,后面几种语法是对它的简化。
param1 -> { statment1; statment2; //............. return statmentM; }
当lambda表达式的参数个数只有一个,可以省略小括号
例如:将列表中的字符串转换为全小写
List
List
param1 -> statment
当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号
例如:将列表中的字符串转换为全小写
List
List
(方法引用和lambda一样是Java8新语言特性,后面会讲到)
Class or instance :: method
例如:将列表中的字符串转换为全小写
List
List
先举例:
//将为列表中的字符串添加前缀字符串
String waibu = "lambda :";
List
List
Long zidingyi = System.currentTimeMillis();
return waibu + chuandi + " -----:" + zidingyi;
}).collect(Collectors.toList());
execStrs.forEach(System.out::println);
输出:
lambda :Ni -----:1474622341604
lambda :Hao -----:1474622341604
lambda :Lambda -----:1474622341604
变量waibu :外部变量
变量chuandi :传递变量
变量zidingyi :内部自定义变量
lambda表达式可以访问给它传递的变量,访问自己内部定义的变量,同时也能访问它外部的变量。
不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。
当在表达式内部修改waibu = waibu + " ";时,IDE就会提示你:
Local variable waibu defined in an enclosing scope must be final or effectively final
编译时会报错。因为变量waibu被lambda表达式引用,所以编译器会隐式的把其当成final来处理。
以前Java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。现在java8对这个限制做了优化,可以不用显示使用final修饰,但是编译器隐式当成final来处理。
在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。
例如:
public class WhatThis {
public void whatThis(){
//转全小写
List
List
System.out.println(this.getClass().getName());
return str.toLowerCase();
}).collect(Collectors.toList());
execStrs.forEach(System.out::println);
}
public static void main(String[] args) {
WhatThis wt = new WhatThis();
wt.whatThis();
}
}
输出:
com.wzg.test.WhatThis
com.wzg.test.WhatThis
com.wzg.test.WhatThis
ni
hao
lambda
本人认为是进一步简化lambda表达式的声明的一种语法糖。
前面的例子中已有使用到: execStrs.forEach(System.out::println);
objectName::instanceMethod
ClassName::staticMethod
ClassName::instanceMethod
前两种方式类似,等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。比如System.out::println等同于x->System.out.println(x);Math::max等同于(x, y)->Math.max(x,y)。
最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()。
可以这么理解,前两种是将传入对象当参数执行方法,后一种是调用传入对象的方法。
构造器引用语法如下:ClassName::new,把lambda表达式的参数当成ClassName构造器的参数 。例如BigDecimal::new等同于x->new BigDecimal(x)。