lambda表达式的适用范围
lambda表达式是对于函数式接口而言的,那么对于函数式接口就需要一个定义:
An informative annotation type used to indicate that an interface type declaration is intended
to be a functional interfaceas defined by the Java Language Specification.
Conceptually, a functional interface has exactly one abstract method.
Since default methods have an implementation, they are not abstract.
If an interface declares an abstract method overriding one of the public methods ofjava.lang.Object,
that also does not count toward the interface's abstract method count since any implementation of the interface
will have an implementation fromjava.lang.Objector elsewhere.
从中我们可以得知函数式接口的几点特征:
- 函数式接口只有一个抽象方法
- default方法某默认实现,不属于抽象方法
- 接口重写了Object的公共方法也不算入内
Stream类方法的泛型设计
如图所示,filter函数中的Predicate函数式接口的泛型形参设置成了? super T,这是为了扩大Predicate的接受范围,Predicate<? super T>可以接收以T及T的父类作为实际参数类型的匿名接口类对象或者说是lambda表达式对象。
而Predicate<T>则不能接收父类作为实际参数的lambda表达式对象(后面记为父类表达式对象),但实际上父类表达式对象所实现的函数对于子类T当然是适用的。所以,应当扩展接受。
同样的,Function<? super T,? extends R>可以接收T及其父类作为实参之一且R及其子类作为另一实参的lambda表达式对象,因为Function的本身功能就是由T得到R的一个函数,那么如果T父类实参类型表达式对象的函数,一定对于T是适用的,由T父类实参类型得到的R子类的函数,对于R也是适用的(返回R子类对象实际上就是返回了R类型的对象)。
lambda表达式组成:
- 由圆括号包括并以逗号隔开的形参列表
- 箭头 ->
- 表达式主体:由单个表达式或者由大括号包括的多个表达式组成。注意当单个表达式时,会直接计算该表达式并返回其值,而无需return关键字。对于返回值为void的方法调用表达式,同样可以不用大括号包起来。
关于lambda表达式的类型,lambda所处的上下文或环境所期望lambda表达式的类型,也就是目标类型,就是lambda表达式的类型,同样的lambda表达式,可以是完全不同的类型。如:
lambda表达式
lambda表达式看起来很像方法声明。也可以将lambda表达式视为匿名方法,即没有名称的方法。
方法引用
lambda表达式是在创建函数式接口的匿名内部类对象的基础上进行优化的。函数式接口中的这个唯一抽象方法的访问权限、参数类型、返回值都是确定好了的。所以我们在写lambda式的时候,Java完全可以通过推断出确定变量类型了,包括返回值、参数个数、访问权限都是可以的,所以这些都是可以省略掉的。参数名不能省略是因为我们写接口抽象方法的实现的时候要用到这些变量,省略了就没法用了。
但也有一种情况是lambda表达式主体中就是直接调用现有的方法,也就是说,其实我们连参数名和表达式主体都可以省略了,只要标明调用的方法来源即可。这就引入了方法引用:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。