lambda 表达式用来表示匿名函数,也就是没有函数名字的函数。
lambda 表达式不能独立执行,因此必须实现函数式接口,并且会返回一个函数式接口的对象。
一、lambda 表达式的语法
方式1:()-> 结果表达式
方式2:参数 ->结果表达式
方式3:(参数 1,参数 2,...,参数 n)-> 结果表达式
第 1 行实现无参方法,单独写一对圆括号表示方法无参数,操作符右侧的结果表达式表示方法的返回值。
第 2 行实现只有一个参数的方法,参数可以写在圆括号里,或者不写圆括号。
第 3 行实现多参数的方法,所有参数按顺序写在圆括号里,且圆括号不可以省略。
可以将 lambda 表达式语法用如下方式理解:
() -> {代码块}
这个方法 按照 这样的代码来实现
二、lambda 表达式实现函数式接口
2.1、认识函数式接口
函数式接口指的是仅包含
一个抽象方法的接口,接口中的方法简单明了地说明了接口的用途。
实例:
interface myInterface{
void run();
}
2.2、lambda 表达式实现无参抽象方法
无参抽象方法在 lambda 表达式中使用“()”
表示
interface SayHiInterface { // 打招呼接口
String say(); // 打招呼的方法
}
public class Test { // 测试类
public static void main(String[] args) {
// lambda表达式实现打招呼接口,返回抽象方法结果
SayHiInterface pi = () -> "lambda 表达式实现无参抽象方法";
System.out.println(pi.say());
}
}
//运行结果
lambda 表达式实现无参抽象方法
2.3、lambda 表达式实现有参抽象方法
1、lambda 表达式中可以用“(al.a2.a3)“
的方法表示有参抽象方法,圆括号里标识符对应抽象方法的参数。
2、如果抽象方法中只有一个参数
,lambda 表达式则可以省略圆括号
interface AdditionInterface { // 加法接口
int add(int a, int b); // 加法的抽象方法
}
public class Test { // 测试类
public static void main(String[] args) {
// lambda表达式实现加法接口,返回参数相加的值
AdditionInterface np = (x, y) -> x + y;
int result = np.add(15, 26); // 调用接口方法
System.out.println("相加结果:" + result); // 输出向相加结果
}
}
//运行结果
相加结果:41
2.4、lambda 表达式使用代码块
当函数式接口的抽象方法需要实现复杂逻辑而不是返回一个简单的表达式的话,就需要在 lambda表达式中使用代码块。lambda 表达式会自动判断返回值类型是否符合抽象方法的定义。
interface CheckGrade {
String check(int grade); // 查询成绩结果
}
public class Test {
public static void main(String[] args) {
CheckGrade g = (n) -> { // lambda实现代码块
if (n >= 90 && n <= 100) { // 如果成绩在90-100
return "成绩为优"; // 输出成绩为优
} else if (n >= 80 && n < 90) { // 如果成绩在80-89
return "成绩为良"; // 输出成绩为良
} else if (n >= 60 && n < 80) { // 如果成绩在60-79
return "成绩为中"; // 输出成绩为中
} else if (n >= 0 && n < 60) { // 如果成绩小于60
return "成绩为差"; // 输出成绩为差
} else { // 其他数字不是有效成绩
return "成绩无效"; // 输出成绩无效
}
}; // 不要丢掉lambda语句后的分号
System.out.println(g.check(89)); // 输出查询结果
}
}
//运行结果
成绩为良
三、lambda 表达式调用外部变量
lambda 表达式无法更改局部变量的值,但是却可以更改外部类的成员变量 (也可以叫作类属性) 的值。
3.1、lambda 表达式无法更改局部变量
局部变量在 lambda 表达式中默认被定义为 final(静态)的,也就是说,lambda 表达式只能调用局部变量,却不能改变其值。
interface VariableInterface1 { // 测试接口
void method(); // 测试方法
}
public class VariableDemo1 { // 测试类
public static void main(String[] args) {
int value = 100; // 创建局部变量
VariableInterface1 v = () -> { // 实现测试接口
int num = value - 90; // 使用局部变量赋值
value = 12; // 更改局部变量,此处会报错,无法通过编译
};
}
}
3.2、lambda 表达式可以更改类成员变量
类成员变量是在 lambda 表达式中不是被 final 修饰的,所以 lambda 表达式可以改变其值。
interface VariableInterface2 { // 测试接口
void method(); // 测试方法
}
public class VariableDemo2 { // 测试类
int value = 100; // 创建类成员变量
public void action() { // 创建类成员方法
VariableInterface2 v = () -> { // 实现测试接口
value = 101; // 更改成员变量,没提示任何错误
};
System.out.println("运行接口方法前value=" + value); // 运行接口方法前先输出成员变量值
v.method(); // 运行接口方法
System.out.println("运行接口方法后value=" + value); // 运行接口方法后再输出成员变量值
}
public static void main(String[] args) {
VariableDemo2 demo = new VariableDemo2(); // 创建测试类对象
demo.action(); // 执行测试类方法
}
}
//运行结果
运行接口方法前value=100
运行接口方法后value=101
四、lambda 表达式与异常处理
很多接口的抽象方法为了保证程序的安全性,会在定义时就抛出异常。但是 lambda 表达式中并没有抛出异常的语法,这是因为 ambda 表达式会默认抛出抽象方法原有的异常,当此方法被调用时则需要进行异常处理。
import java.util.Arrays;
import java.util.List;
class test {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 0);
numbers.forEach(number -> {
try {
int result = 10 / number;
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
});
}
}
//运行结果
Result: 10
Result: 5
Result: 3
Result: 2
Result: 2
Error: / by zero