这一部分主要记录了Java中Lambda表达式的使用方式和方法引用。Lambda表达式是函数式编程思想的体现,函数式编程思想尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”。Lambda表达式遵循“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导。
方法引用是Lambda的孪生兄弟,与Lambda表达式同样可以根据上下文进行推导,使用方法引用可以减少代码复杂度。
文章结构分为「Lambda表达式的格式与使用、Lambda表达式与匿名内部类的区别、方法引用概述、Lambda表达式支持的方法引用」四个部分。
Lambda表达式的格式与使用
使用前提
- 必须要有接口,接口只有一个抽象方法
- 必须有上下文环境才能推到Lambda对应的接口
Lambda表达式的标准格式
格式
标准格式由三要素组成:形式参数、箭头、代码块
1 | (形式参数) -> {代码块(具体要做的事情)} |
示例
示例要求:计算x + y
,使用有参有返回的抽象方法
代码实现:
接口类
1 | public interface Addable { |
主类
1 | public class AddableDemo { |
说明
useAddable(Addable a)
需要传入一个Addable接口
的实现类。传入后,useAddable(Addable a)
方法就可以调用Addable接口
中的a.add(int x, int y)
的方法。所以主类中我们就传入了一个Labmda表达式,相当于重写了接口类的 add(int x,int y)
方法。
此处也可以使用匿名内部类重写a.add(int x, int y)
来实现,但较为麻烦,具体实现如下:
1 | useAddable(new Addable() { |
Lambda表达式的缩略形式
格式
Lambda表达式可以有条件的缩略,具体缩略情况如下:
- 省略参数类型
- 省略小括号:参数只有一个
- 省略大括号和分号,以及return:如果只有一条语句
示例
用缩略写法表示上一个示例
1 | useAddable((x, y) -> x + y); |
Lambda表达式和匿名内部类的区别
- 所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
- 使用限制不同
- 如果接口抽象方法1个:都可以
- 如果接口抽象方法多个:匿名内部类only
- 实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
方法引用概述
方法引用符
1 | :: |
推导与省略
- 如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导
- 如果使用方法引用,也是同样可以根据上下文进行推导
- 方法引用是Lambda的孪生兄弟
示例:
1 | public class PrintableDemo { |
Lambda表达式支持的方法引用
支持如下方法的方法引用:
- 引用类方法
- 引用对象实例方法
- 引用类的实例方法
- 引用构造器
引用类方法
格式:
类名::静态方法
范例:
Integer::parseInt
其调用的方法是:public static int parseInt(String s)
示例
练习:
- 定义一个接口(Converter),里面定义一个抽象方法:int convert(String s);
- 定义一个测试类(ConverterDemo),在测试类中提供两个方法
一个方法是:useConverter(Converter c)
一个方法是主方法,在主方法中调用useConverter方法
1 | public class ConverterDemo { |
引用对象实例方法
格式
对象::成员方法
范例
"HelloWorld"::toUpperCase String
类中的方法:public String toUpperCase() 将此String所有字符转换为大写
传参
Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数
示例
1 | public class PrinterDemo { |
引用类的实例放法
引用类的实例方法,其实就是引用类中的成员方法
格式
类名::成员方法
范例
String::substring
使用的public String substring(int beginIndex,int endIndex)
(从beginIndex开始到endIndex结束,截取字符串。返回一个子串,子串的长度为endIndex-beginIndex)
传参
Lambda表达式被类的实例方法替代的时候,第一个参数作为调用者,后面的参数全部传递给该方法作为参数。
示例
1 | public class MyStringDemo { |
引用构造器(构造方法)
格式 :
类名::new
范例 :
Student::new
传参
Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数
示例
练习
定义一个类(Student),里面有两个成员变量(name,age) 并提供无参构造方法和带参构造方法,以及成员变量对应的get和set方法
定义一个接口(StudentBuilder),里面定义一个抽象方法**
Student build(String name,int age);
**定义一个测试类(StudentDemo),在测试类中提供两个方法
一个方法是:useStudentBuilder(StudentBuilder s)
一个方法是主方法,在主方法中调用useStudentBuilder方法
1 | public class StudentDemo { |