Java8新特性-Lambda表达式(第二天)
-- 为啥要用Lambda表达式?
Lambda表达式的作用
--简化匿名内部类
语法
(parameters) -> expression
或
(parameters) ->{ statements; }
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
在哪里使用?
可以在函数式接口上使用Lambda。(注:函数式接口就是只定义一个抽象方法的接口,使用@FunctionalInterface注解标志函数式接口)
变量作用域
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
public static void main(String args[]){
String str = "Hello! ";
Output output = message -> {
str = "hi"; //编译出错
System.out.println(str + message);
};
output.sayMessage("Runoob");
}
interface Output{
void sayMessage(String message);
}
实践:自己动手做一个函数式接口和使用Lambda表达式
这里用到了一个 环绕执行模式,当在执行某些业务的时候,有大量的准备工作和收尾工作要做的时候,可以抽离出共同的部分,围绕着执行处理的重要代码来操作,如下图。例如jdbc的操作和文件资源管理的操作。
在这里列举一个对字符串加上一个“TAG”,并且将字符串转换为大写字母的例子。
动手之前先看看之前的做法,一般都会考虑封装一个方法出来,如下:
public static String toUpperCaseTest(String s) {
s += "tag";
return s.toUpperCase();
}
但是这样的话,假如再来一个转为小写字母的需求,又要再定义一个:
public static String toLowerCaseTest(String s) {
s += "tag";
return s.toLowerCase();
}
中间的操作 s += "tag"; 就会大量的重复了。
接下来我们看下Lambda表达式的做法
第1步:行为参数化
将执行大写还是小写的行为当做参数来传递
String formatJsonString = formatJsonString(cc -> cc.toUpperCase(), "hello");
第2步:使用函数式接口来传递行为
定义一个可供传递的函数式接口
@FunctionalInterface
interface FormatStr{
String format(String s);
}
formatJsonString将这个接口当做参数传递
public static String formatJsonString(FormatStr formatStr,String s) {
....
}
第3步:执行一个行为
在formatJsonString方法中调用接口的抽象方法,此时formatJsonString是完全不知道实现的,仅是传递。同时,该方法也把共同模块抽离出来了。
// 格式化字符串
public static String formatJsonString(FormatStr formatStr,String s) {
//共同模块,给字符串统一加上日期后缀
s += "tag";
return formatStr.format(s);
}
第4步:传递Lambda
大概是想干啥就干啥了
//你想返回大写
String formatJsonString = formatJsonString(cc -> cc.toUpperCase(), "hello");
//你想返回小写
String formatJsonString = formatJsonString(cc -> cc.toLowerCase(), "hello");
//你想截取一小段
String formatJsonString = formatJsonString(cc -> cc.substring(0,2), "hello");
...
Lambda表达式就学到这里啦,继续努力吧