1.Lambda表达式基础
类似于匿名方法,一个没有名字的方法
参数,箭头,表达式语句
可以忽略写参数类型
坚决不声明返回值类型
没有public/protected/private/static/final等修饰符
单句表达式,将直接返回值,不用大括号
带return语句, 算多句,必须用大括号
无参数,仅保留括号,箭头,表达式
1 | new Thread( |
- 一个参数,可省略括号,箭头,表达式
1 | Adder c1 = |
- 如果有返回值,返回值类型会在上下文推断出来的,无需声明
- 只在某几个分支有返回值,这样是不合法的
1 | Adder c2 = |
2.函数式接口
- 是一个接口,符合Java接口的定义
- 只包含一个抽象方法的接口
- 可以包括其他的default方法、static方法、private方法
- 由于只有一个未实现的方法,所以Lambda表达式可以自动填上这个尚未实现的方法
- 采用Lambda表达式,可以自动创建出一个(伪)嵌套类的对象(没有实际的嵌套类class文件产生),然后使用,比真正嵌套类更加轻量,更加简洁高效
系统自带的函数式接口
- 涵盖大部分常用的功能,可以重复使用
- 位于java.util.function包中
Predicate<T>: 接收一个参数,返回一个布尔值
1 | Predicate<String> oddLength = s -> |
Consumer<T>:接收一个参数,做操作,无返回
1 | Consumer<String> printer = s -> |
Supplier<T>:无输入参数,返回一个数据
1 | Supplier<String> planetFactory = () -> |
Function<T>:接收一个参数,返回一个参数
1 | Function<String, String> upper = s -> |
3.方法引用
Lambda表达式支持传递现有的类库函数
Class::staticMethod,如 Math::abs方法
Class::instanceMethod,如String::compareToIgnoreCase方法
object::instanceMethod,如System.out::println方法
- 支持this::instanceMethod 调用
- 支持super::instanceMethod调用
Class::new,调用某类构造函数,支持单个对象构建
Class[]::new,调用某类构造函数,支持数组对象构建
Class::staticMethod
- 等价于提供方法参数的Lambda表达式
- Math::abs 等价于 x -> Math.abs(x)\
1 | public class ClassStaticMethodTest { |
Class::instanceMethod
- 第一个参数将变成方法的执行体
- String::compareToIgnoreCase等价于(x,y)->x.compareToIgnoreCase(y)
1 | String[] planets = new String[] { |
object::instanceMethod
- 等价于提供方法参数的Lambda表达式
- System.out::println等价于x->System.out.println(x)
1 | public class ObjectInstanceMethodTest { |
- 支持this::instanceMethod
1 | public class ThisInstanceMethodTest { |
- 支持super::instanceMethod
1 | public class SuperInstanceMethodTest extends Father{ |
Class::new
1 | Supplier<Person> s = Person::new; |
Class[]::new
1 | IntFunction<int[]> intArray = int[]::new; |
4.Lambda表达式应用
- Lambda表达式没有存储目标类型(target type)的信息
- 重载调用,依据重载的规则和类型参数推理
变量遮蔽
- Lambda表达式和匿名内部类/局部内部类一样,可以捕获变量(capture variables),即访问外部嵌套块的变量
- 但是变量要求是final或者是effectively final的
- Lambda表达式没有变量遮蔽问题,因为它的内容和嵌套块有着相同的作用域
- 在Lambda表达式中,不可以声明与(外部嵌套块)局部变量同名的参数或者局部变量
- 表达式中的this,就是创建这个表达式的方法的this参数
优先级
- Lambda表达式优先级比嵌套类要高
- 短小精干,本身可以自描述的
- 无法创建命名实例,无法获取自身的引用(this)
- 方法引用比自定义Lambda表达式的优先级高
- 系统自带的方法引用更简洁高效
- 对于复杂的Lambda表达式,采用方法引用比内嵌Lambda表达式更清晰,更容易维护
- 坚持使用标准的函数式接口
- 更容易学习,提高互操作性