文章目录
Lambda表达式是Java函数式编程的核心概念之一,是一种语法糖
- 语法糖(Syntactic sugar):计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用
- Java中其他的语法糖:for-each,断言等等
用于简化实现函数式接口Functional Interface
回顾下Interface
Why Interface
接口用来定义一个协议或约定,只提供抽象方法
- 抽象方法 Abstract Method:只声明方法,不提供方法的具体实现
- 但JDK1.8以后,接口可以有方法体与具体实现的方法(default)
将接口的声明与具体实现分开,业务中只需要关心方法,不需要关心具体的实现类
从而实现代码的解耦和模块化
Interface例子
需求
通过一个方法发送多种不同形式的消息,比如Email邮件消息、SMS短消息
实现需求
-
定义
Message
接口public interface Message{ void send(); // abstract method }
-
Email
实现Message
接口public class Email implements Message{ String email; public Email() { } @Override public void send() { System.out.println("This is an email."); } }
-
Sms
实现Message
接口public class Sms implements Message{ String phoneNumber; public Sms() { } @Override public void send() { System.out.println("This is a sms."); } }
-
main中测试
public class Main { public static void main(String[] args) { Message email = new Email(); Message sms = new Sms(); sendMessage(email); sendMessage(sms); } static void sendMessage(Message message){ // 参数类型为Message接口,可以传入Email或SMS对象 message.send(); } }
Lambda表达式
Why Lambda
可以看出,上面的例子中仅发送一条消息,也需要很多步骤:
- 先根据Message接口实现Email或Sms类
- 在实现类中实现接口的抽象方法
- 创建Message的Email或Sms实例
- 发送
Lambda表达式可以提供一种快速简介的方式实现接口,抽象方法的实现直接在Lambda表达式里定义
Lambda表达式
(parameters)->{statements;}
()
括号 Parentheses:对应抽象方法的括号,里面是抽象方法的参数- 如果只有一参数,可以省略:
parameter ->{statements;}
- 如果只有一参数,可以省略:
-
连字号 Hyphen>
箭头Arrow{}
大括号Curly Braces:Lambda体,对应抽象方法的大括号,里面放具体行为- 如果只有一行,可以省略:
(parameters) -> expression
- 如果只有一行,可以省略:
Lambda表达式实现send()
无参数的抽象方法
public interface Message{
void send(); // abstract method
}
- 一行:
(parameters) -> expression
sendMessage(() ->
System.out.println("This is an email.");
);
输出:
This is an email.
- 多行:
(parameters)->{statements;}
sendMessage(() -> {
System.out.println("This is an email.");
System.out.println("Hi there!");
});
输出:
This is an email.
Hi there!
有参数的抽象方法
public interface Message{
void send(String name); // abstract method
}
public class Main {
public static void main(String[] args) {
sendMessage((name) -> {
System.out.println("This is an email to " + name);
}
);
}
static void sendMessage(Message message){
// 参数类型为Message接口,可以传入Email或SMS对象
message.send("Hansdas");
}
}
由于只有一个参数跟一行代码,Lambda表达式可以简化
public class Main {
public static void main(String[] args) {
sendMessage(name ->
System.out.println("This is an email to " + name);
);
}
static void sendMessage(Message message){
// 参数类型为Message接口,可以传入Email或SMS对象
message.send("Hansdas");
}
}
多参数、有返回值的抽象方法
public interface Message{
string send(String name, String title); // abstract method
}
public class Main {
public static void main(String[] args) {
sendMessage((name, title) -> {
System.out.println("This is an email to " + title+ " " +name);
return "success!";
}
);
}
static void sendMessage(Message message){
// 参数类型为Message接口,可以传入Email或SMS对象
String status = message.send("Hansdas", "Mr");
}
}
赋值给变量
Lambda表达式也可以赋值给对应接口类型的变量
public class Main {
public static void main(String[] args) {
Message lambda = (name, title) -> {
System.out.println("This is an email to " + title+ " " +name);
return "success!";
};
}
static void sendMessage(Message message){
// 参数类型为Message接口,可以传入Email或SMS对象
String status = message.send("Hansdas", "Mr");
}
}
Email or SMS?
回到开始的需求,需要发送Email或SMS类型的信息,此时不需要创建对应类实现接口、实例化对象、调用对应方法
只需要早Lambda表达式中稍作修改
public class Main {
public static void main(String[] args) {
sendMessage((name, title) -> {
System.out.println("This is an SMS to " + title+ " " +name);
return "success!";
}
);
}
static void sendMessage(Message message){
// 参数类型为Message接口,可以传入Email或SMS对象
String status = message.send("Hansdas", "Mr");
}
}
Lambda表达式的限制
- Lambda表达式只能用于函数式接口
- 函数式接口Functional Interface:有且只有一个抽象方法的接口
- 因为接口如果有多个抽象方法,lambda不值得要实现哪个抽象方法
- 可以使用
FunctionalInterface
标注函数式接口,建议使用,- 但不是必须的,只要满足函数式接口【只有一个抽象方法】的条件,Java会自动将其作为函数式接口
Reference
依然来自AlbertShen