java8新特性之lambda表达式与函数式接口
前言
本文的思路是先介绍lambda重要特征并给出实际用例,再介绍lambda与函数式接口的关系引出函数式接口,再叙述函数式接口的相关特点。
lambda重要特征
1、可选的大括号
当方法体内只包含了一个语句时,可以选择省略大括号,方法体末尾不需要分号。如上例,System.out.println("lambda1")语句就没有用大括号括起来,语句末尾也没有分号。
如果方法体有多行,就要用{}括起来,末尾也要跟上分号。
2、可选的类型声明
lambda表达式有类型推断机制,在上下文信息足够多的情况下能够推断出参数表的类型而无需指明。
比如Collections.sort()
可以指明a和b的参数类型为String
也可以省略参数类型,因为java可以根据list的类型推断出s1和s2的参数类型
3、 可选的参数圆括号
只有一个参数时可以省略参数圆括号,无参或是多参都要写上圆括号
4、可选的参数关键字
如果方法体只有一个表达式并且未使用大括号,那么编译器会自动返回值。
什么时候可以简写为lambda
我们分别来看两个匿名内部类的简写,分析为什么它们可以简写成lambda,总结出什么情况下可以简写为lambda。
简写为
观察上面两个匿名内部类,我们可以发现:它们的接口名以及方法名都被擦拭掉了。所以我们可以得出:可以被简写的接口中的抽象方法唯一,因为不唯一的话方法名被擦拭了那就无法识别是哪个方法了。这也就是我们的函数式接口:只有一个抽象方法的接口(不包含一些特殊情况,这些特殊情况下面会介绍)。
函数式接口
JDK1.8前的函数式接口:
JDK1.8新定义的函数式接口:
函数式接口是只能有一个抽象方法的接口,但这也有例外,接口可以定义Object类的public方法,但这些方法的方法签名必须和Object类的一样,这些方法也是抽象方法,但并不影响该接口成为函数式接口:
该接口虽然多出了hashCode这个抽象方法,但仍是函数式接口,因为hashCode是Object类的public方法。
接口中的抽象方法和默认方法不会影响该接口成为函数式接口:
该接口中虽然有print这个默认方法,print1这个抽象方法,但仍是函数式接口。
@FunctionnalInterface作用
函数式接口可以不用@FunctionalInterface注解修饰,非函数式接口一定不能用@FunctionalInterface修饰,因为@FunctionalInterface会在编译期检查该接口是否为函数式接口,如果不是,则会编译错误。