Lambda函数特点:
- 匿名——写得少想的多。
- 函数——lambda有参数列表、函数主体、返回类型,有可以抛出的异常列表。
- 传递——lambda表达式可作为参数传递给方法或存储在变量中。
- 简介
Lambda隐含return语句(可以显式地使用return)。
Lambda有三个部分(更多示例: http://www.cnblogs.com/Hu-Yan/p/7955550.html)
- 参数列表
- 箭头
- Lambda主体
return是一个控制流语句,要使它在lambda表达式中有效需要使用{}。
" ExampleString "是一个表达式,不是一个语句,要使它在lambda表达式中有效需要去除{} 和 ; ,可用显式的返回语句。
函数式接口:只定义一个抽象方法的接口(即使接口中还含有默认方法)。注意该接口是否继承了别的方法。
Lambda函数允许你直接以内联的形式为函数式接口的抽象方法提供实现, 并把整个表达式作为函数式接口的实例。
函数式接口的抽象方法的签名基本上是lambda表达式的签名。这种抽象方法叫做函数描述符。签名匹配,lambda表达式才会有效。
常见的函数式接口:Comparable, Runnable, Callable, Predicate, Consumer, Function …
在你需要表示一个涉及类型T的布尔表达式时,则可以使用Predicate接口。
如果需要访问类型T的对象,并对其执行某些操作,则可以使用Consumer接口(抽象方法:accept,接受泛型的对象,无返回。)。
如果需要将输入对象的信息映射到输出,则可以使用Function接口,它定义了apply方法——接受一个泛型T的对象并返回一个泛型R的对象。
装箱(boxing)机制:Java类型要么是引用类型,要么是原始类型。但是泛型只能绑定到引用类型。拆箱(unboxing):将 引用类型转换为对应的原始类型。
装箱后的值需要更多内存,并需要额外内存搜索来获取被包裹的原始值。
针对专门的输入参数类型的函数式接口的名称都要加上相对应的原始类型。如:DoublePredicate、IntConsumer … Function接口还有针对输出参数类型的变种: ToIntFunction<T> 等。
使用案例 | 对应函数式接口 |
布尔表达式 | Predicate |
创建对象 | Supplier |
使用一个对象 | Consumer |
从一个对象中选择/提取 | Function / ToIntFunction |
合并两个值 | intBinaryOperator |
比较两个对象 | Comparator / BiFunction / ToIntBiFunction |
任何函数式接口都不允许抛出受检异常(checked exception)。如果你需要lambda表达式抛出异常,有两种方法:
- 自定义一个函数式接口, 并声明受检异常。
- 把lambda表达式办函在一个try/catch块中。
Lambda表达式需要的类型称为目标类型。其类型检查过程如下所示:
- 找出方法的声明
- 要求它是目标类型的第二个正式参数。
- 函数式接口定义了一个抽象方法
- 该抽象方法描述了一个函数描述符
- 方法的任何实际参数都需匹配这个要求。
Caution:如果lambda函数抛出异常,那么抽象方法所声明的throws语句必须与之匹配。
同一个Lambda表达式可以与不同的函数式接口联系起来,只要它们的抽象方法签名能够兼容。
如果一个Lambda的主体是一个语句表达式,他就和一个返回void的函数描述符兼容。
当Lambda仅有一个类型需要推断的参数时,参数名称的两边的括号也可以省略。
方法引用的基本思想:如果一个lambda表达的知识"直接调用这个方法",那最好还是用名称来调用它,而不是去描述如何调用它。
方法引用的使用:目标引用放在分隔符::前,方法的名称放在后面。
方法引用主要有三种:
- object::instanceMethod(指向现有对象的实例方法的引用,其思想是——调用一个已存在的外部对象的方法)
- ClassName::staticMethod(指向静态方法的方法引用)
- ClassName::instanceMethod(指向任意类型实例方法的方法引用,思想为——引用一个对象的方法,而这个对象本身是lambda的一个参数。)
Lambda表达式重构等价的方法引用 :
Lambda | 方法引用 |
(arg0, rest) -> arg0.instanceMethod(rest) | ClassName :: instanceMethod |
Lambda | 方法引用 |
(args) -> ClassName.staticMethod(args) | ClassName :: staticMethod |
Lambda | 方法引用 |
(ags) -> expr.instanceMethod(args) | expr :: instanceMethod |
方法引用的签名必须和上下文类型匹配。
创建一个构造函数的引用——ClassName :: new
构造函数参数个数 | 使用构造函数引用 |
1 | Supplier<T> |
2 | Function<T, R> |
3 | BiFunction<T, U, R> |
>= 4 |