当使用 Lambda 表达式代替匿名内部类创建对象时,Lambda 表达式的代码块将会代替实现抽象方法的方法体,Lambda 表达式就相当于一个匿名方法。
Lambda 表达式由三部分组成:
- 形参列表。形参列表允许省略形参类型,如果形参列表中只有一个参数,甚至连形参列表的圆括号都可以省略。
- 箭头
->
- 代码块。如果代码块只有一条语句,Lambda 表达式允许省略代码块的花括号。如果代码块只有一条 return 语句,甚至可以省略 return 关键字。
函数式接口
Lambda 表达式实际上将会被当成一个”任意类型”的对象,到底需要当成何种类型的对象,这取决于运行环境的需要。Lambda 表达式只能为函数式接口创建对象。
方法引用与构造器引用
前面介绍过,如果 Lambda 表达式的代码块只有一条语句,程序就可以省略 Lambda 表达式中的代码块的花括号。不仅如此,如果 Lambda 表达的代码块只有一条语句,还可以在代码块中使用方法引用和构造器引用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35先定义一个接口类
interface Converter
{
Integer convert(String from);
}
//方法引用代替 Lambda 表达式:引用类方法
Converter converter= from -> Integer.valueOf(from);
//函数式接口中被实现方法的全部参数传给该类作为参数
Converter converter= Integer::valueOf;
//方法引用代替 Lambda 表达式:引用特定对象的实例方法
Converter converter= from -> "fkit.org".indexOf(from);
//函数式接口中被实现方法的全部参数传给该方法作为参数
Converter converter= "fkit.org"::indexOf;
//方法引用代替 Lambda 表达式:引用某类对象的实例方法
interface MyTest
{
String test(String a,int b,int c);
}
MyTest mt= (a,b,c) -> a.substring(b,c);
//函数式接口中被实现方法的第一个参数作为调用者
//后面的参数全部传给该方法作为参数
MyTest mt= String::substring;
//引用构造器代替 Lambda表达式
interface YourTest
{
JFrame win(String title);
}
//使用 Lambda 表达式创建 YourTest 对象
YourTest yt= (String a) -> new JFrame(a);
等同于
YourTest yt=JFrame::new;
Lambda 表达式于匿名内部类的联系和区别
- Lambda表达式与匿名内部类一样,都可以直接访问局部变量,以及外部类的成员变量(包括成员变量和类变量);
- Lambda表达式创建的对象与匿名内部类生产的对象一样,都可以直接调用从接口中继承的默认方法;
- 匿名内部类可以为任意接口创建实例-不管接口包含多少个抽象方法,只有匿名内部类实现所有的抽象方法即可;但Lambda表达式只能为函数式接口创建实例;
- 匿名内部类可以为抽象类甚至普通类创建实例,但Lambda表达式只能为函数式接口创建实例;
- 匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法;但Lambda表达式的代码块不允许调用接口中定义的默认方法;