Java中的Lambda表达式是Java 8引入的一个重要特性,它提供了一种清晰且简洁的方式来表示只有一个抽象方法的接口(称为函数式接口)的实例。Lambda表达式本质上是一个匿名方法,它可以让你的代码更加简洁易读。
基本语法
Lambda表达式的基本语法如下:
(parameters) -> expression
或
(parameters) -> { statements; }
- parameters:参数列表。参数的类型可以省略,编译器会根据上下文推断出参数的类型。
- ->:Lambda操作符,读作“goes to”。
- expression:一个表达式,其计算结果将作为Lambda表达式的返回值。表达式的类型应与函数式接口的返回类型兼容。
- statements:一个代码块,包含多个语句。如果Lambda表达式需要执行多个语句,则应该使用花括号
{}
包围起来,并且如果有返回值,需要显式地使用return
语句。
示例
假设我们有一个函数式接口Greeting
,它有一个抽象方法greet
,该方法接受一个String
参数并返回一个String。
@FunctionalInterface
interface Greeting {
String greet(String name);
}
使用Lambda表达式实现Greeting
接口
Greeting greeting = name -> "Hello, " + name + "!";
System.out.println(greeting.greet("World")); // 输出:Hello, World!
在这个例子中,我们直接使用了Lambda表达式来创建Greeting
接口的实例。Lambda表达式name -> "Hello, " + name + "!"
简洁地实现了greet
方法。
假设我们有一个函数式接口 FunctionalInterface
,它定义了一个抽象方法 int operate(int a, int b)
。我们可以使用 Lambda 表达式来创建该接口的实例:
@FunctionalInterface
interface FunctionalInterface {
int operate(int a, int b);
}
public class LambdaExample {
public static void main(String[] args) {
// 使用 Lambda 表达式创建 FunctionalInterface 的实例
FunctionalInterface fi = (int a, int b) -> a + b;
// 调用 operate 方法
int result = fi.operate(3, 4);
System.out.println("Result: " + result); // 输出:Result: 7
}
}
参数列表
参数列表可以省略类型,编译器可以根据上下文推断出来:
FunctionalInterface fi = (a, b) -> a * b; // 类型推断
Lambda 体
如果 Lambda 体只包含一个表达式,可以省略 {}
:
FunctionalInterface fi = (a, b) -> {
int c = a / b;
return c;
}; // 多条语句
使用 Lambda 表达式
假设我们有一个 Comparator
接口,我们想根据对象的某个属性进行排序:
import java.util.Arrays;
import java.util.Comparator;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ComparatorExample {
public static void main(String[] args) {
Person[] people = {
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
};
// 使用 Lambda 表达式按照年龄排序
Arrays.sort(people, (p1, p2) -> p1.getAge() - p2.getAge());
// 输出排序后的结果
for (Person person : people) {
System.out.println(person);
}
}
}
假设运行上述代码,输出将是:
Person{name='Bob', age=25}
Person{name='Alice', age=30}
Person{name='Charlie', age=35}
注意事项
- 函数式接口:Lambda表达式只能用于实现函数式接口(即只有一个抽象方法的接口)。
- 类型推断:Lambda表达式中的参数类型可以省略,编译器会根据上下文自动推断。
- 访问权限:Lambda表达式可以访问外部变量(即它们所在的作用域中的变量),但这些变量必须是
final
或实际上是final
的(即只被赋值一次)。从Java 8开始,这个限制被放宽了,只要变量在Lambda表达式外部没有被修改,就可以被捕获。 - 异常处理:如果Lambda表达式抛出的异常被函数式接口的抽象方法声明抛出,则不需要在Lambda表达式中显式地处理这些异常。否则,需要处理或声明抛出这些异常。
总结
->
符号用于分隔 Lambda 表达式的参数列表和 Lambda 体。- Lambda 表达式提供了一种简洁的方式来定义函数式接口的实现。
- 参数列表可以省略类型,编译器会根据上下文推断类型。
- Lambda 体可以是一个表达式或一组语句。