–在学Lambda之前需要先学习内部类和匿名类相关知识–
在学习Lambda之前需要学习一点相关知识
1.函数式编程
虽然 Java 不是函数式语言,但 Java 8 Lambda 表达式让java也拥有函数式编程的能力。
函数式编程中的“函数”不是指编程语言中的函数(方法),而是指数学中的函数。 比如 y=2x+5 这个函数,你只需要关注 输入变量x 和 输出变量y 至于计算方法我们交给编译器而不是自己写。
简单来说,函数式编程的意义在于简化原本复杂的代码,我们经常写一些重复的,冗余的代码模块(比如匿名类),这些重复的部分完全可以由编译器帮我们完成。而且,代码量的增加意味着出错概率增大。
所以,函数式编程的意义在于,合并了重复编写的内容,我们可以更快地获得更可靠的代码。这也很像框架。属于对编程过程的简化。
2.函数式接口(Functional Interface)
写Lambda是有代价的,它也需要接口的支持,必须是函数式接口才可以。
函数式接口也是java1.8新特性,函数式接口就是指一个有且仅有一个抽象方法的接口。
比如,你肯定对Runnable接口不陌生,它是多线程的一种实现方式(不知道也没关系)
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
在Runnable接口中,你可以看到,只有一个抽象方法 run();
而且,你也注意到了接口上面的@FunctionalInterface 注解,这是java1.8新注解,添加这个注解,编译器会检查当前接口是否为函数式接口,如果不是,编译器会报错。不写也没事儿,但写上更好,防马虎出错。
至此,基础讲完了,下面讲Lambda。
3.Lambda表达式
我们先来了解Lambda表达式的语法
基本语法:
(parameters) -> expression 或 (parameters) ->{ statements; }
翻译
(参数) -> 表达式 或 (参数) ->{ 声明; }
左侧为输入参数,右侧为对参数执行的运算,中间用 -> 来连接 , 这很像数学中的函数,输入变量,然后函数处理变量。
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
以上只是基础语法,Lambda最常用的场景就是替代匿名类。
常用的实现线程:
new Thread((new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类 实现线程");
}
})).start();
//lambda
new Thread( () -> System.out.println("lambda实现线程")).start();
你可能有个疑问,Lambda语法明白了,但上面的匿名类为什么可以直接写成下面的Lambda表达式? 请往下看。
首先,这是原始的匿名内部类
前面说过,可用Lambda的接口都是函数式接口,也就是说每个接口里一定只有一个抽象方法,既然这样,那方法名字就是多余的,也就是说反正只有一个抽象方法,名字叫什么都无所谓。所以可以去掉抽象方法声明:
那既然我们要使用的只是接口中唯一的方法中的实现的方法体(有点绕),那接口名字又有何用呢!所以只留下接口中抽象方法的实现的内容就可以了,也就是只剩一行输出语句:
融合进Lambda语法,变成现在这个样子了:
由于这是个没有参数的方法,所以左边参数是空的。
4.总结
任何 Lambda 表达式的基本语法是:
参数,接着 ->,可视为“产出”。
-> 之后的内容都是方法体。
[1] 当只用一个参数,可以不需要括号 ()。 然而,这是一个特例。
[2] 正常情况使用括号 () 包裹参数。 为了保持一致性,也可以使用括号 () 包裹单个参数,虽然这种情况并不常见。
[3] 如果没有参数,则必须使用括号 () 表示空参数列表。
[4] 对于多个参数,将参数列表放在括号 () 中。
本质上,Lambda就是匿名类,java在编译的时候会自动把Lambda转换成匿名类。
注意:
Lambda表达式虽然带来了代码的简洁,但是也有其局限性。
- 可读性差,与啰嗦的但是清晰的匿名类代码结构比较起来,Lambda表达式一旦变得比较长,就难以理解
- 不便于调试,很难在Lambda表达式中增加调试信息,比如日志
- 版本支持,Lambda表达式在JDK8版本中才开始支持,如果系统使用的是以前的版本,考虑系统的稳定性等原因,而不愿意升级,那么就无法使用。
- Lambda比较适合用在简短的业务代码中,并不适合用在复杂的系统中,会加大维护成本。来源:how2j教程