更新时间:2019-12-10 15:38:44 来源:极悦 浏览2776次
Lambda表达式
经常听到一个概念:闭包。闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
其实,就是Lambda表达式,Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
出现原因
面向对象式编程就应该纯粹的面向对象,于是经常看到这样的写法: 如果你想写一个方法,那么就必须把它放到一个类里面,然后new出来对象,对象调用这个方法。最大的问题就在于其冗余的语法,有人戏称匿名类型导致了“高度问题”(height problem): 大多匿名内部类的多行代码中仅有一行在做实际工作。因此JAVA8中就提供了这种“函数式编程”的方法 —— lambda表达式,供我们来更加简明扼要的实现内部匿名类的功能。
也就是说,你在某处就真的只需要一个能做一件事情的函数而已,连它叫什么名字都无关紧要。 Lambda 表达式就可以用来做这件事。
语法介绍
函数式接口
函数式接口(Functional Interface):定义的一个接口,接口里面必须 有且只有一个抽象方法(可以有默认方法和静态方法) ,这样的接口就成为函数式接口。在可以使用lambda表达式的地方,方法声明时必须包含一个函数式的接口。
如果我们提供的这个接口包含一个以上的Abstract Method,那么使用lambda表达式则会报错。 因为这不是函数式接口。
例如:
Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。你不加的话,就不做检查。
注意点:
函数式接口中可以额外定义多个Object的public方法一样抽象方法:接口最终有确定的类实现, 而类的最终父类是Object。 因此函数式接口可以定义Object的public方法。
函数式接口的抽象方法可以声明 可检查异常(checked exception)。 在调用目标对象的这个方法时必须catch这个异常。
函数式接口中除了那个抽象方法外还可以包含静态方法、默认方法。
任何函数式接口都可以使用lambda表达式替换。 例如系统已经有的:ActionListener、Comparator、Runnable。JDK 8之前已有的函数式接口:
另外,还有好多好多的接口,可以到具体的java.util.function包下去看一下。
那么在参数为这些接口的地方,我们就可以直接使用lambda表达式了!
Lambda表达式
当lambda表达式的参数个数只有一个,可以省略小括号;
当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号。自动返回该语句的结果。
Lambda 表达式的简单例子:
特性与注意点
lambda表达式中的this概念
在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。
不举例子了,是真的。
类型推导
先上个小例子举例:
编译器负责推导lambda表达式的类型。它利用lambda表达式所在上下文所期待的类型进行推导, 这个被期待的类型被称为目标类型。就是说我们传入的参数可以无需写类型了!
因此,在定义函数时:
MathOperation addition = (a, b) -> a + b;
我们并没有在入参里说明入参a,b的类型,因为如果没有类型推导,得这么写:
(int a, int b) -> a + b;
2.3.3 函数嵌套
我们知道,系统已经帮我们创建了几个函数时接口,例如:
它的代码如下:
它内置了两个写出了默认实现的方法,基于它们,可以实现函数的嵌套。
首先,这是一个函数式接口,真正的抽象函数只有一个。
接下来我们看一下,compose() 和 andThen() 这两个默认实现为什么能够实现级联操作:首先我们定义了两个,分别是fun1和fun2。那,对于fun1.apply("a")操作,我们就是将“a”作为参数,传给函数fun1,然后fun1把它执行掉,故输出“a>”。
我们着重要分析的是fun1.compose(fun2).apply("b")。分析compose函数,before=fun2。因此,(V v) -> apply(before.apply(v))最终变为:(V v) -> apply(fun2.apply(v)),即为:fun1.apply(fun2.apply(v)),因此是v先给fun2处理,得到“b+”;然后“b+”传给fun1,得到“b+>”。因此,实现了两个函数的嵌套。
同理,fun1.andThen(fun2).apply("c"),after=fun2,因此(T t) -> after.apply(apply(t));即为:fun2.apply(apply(t))。apply(t)是针对于fun1的,因此是fun1处理完完后又fun2处理。
不过,这两个方法是系统内置的,会用就可以了。
3 总结
Java8 提供的Lambda表达式使得Java程序更为便捷、灵活,不过在使用Lambda表达式时也要注意相关指向问题,防止迷失。
关于Java8中Lambda表达式的介绍就到这里,在后续的文章中我们将介绍Java8中的其它特性。
以上就是极悦注册机构小编介绍的“Java中什么是lambda表达式”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习