Lambda表达式是否可以捕获变量?如果可以,有哪些要求?代码举例讲解

Lambda 表达式可以捕获外部变量。但是,有以下几点要求:

  1. Lambda 表达式只能捕获 final 或 effectively final 变量。
    effectively final 变量指的是那些在 Lambda 表达式创建后不会再被修改的变量。
    例如:
final int num = 1; 
Converter<Integer, String> converter = (x) -> String.valueOf(x + num);

这里 num 是 final 变量,可以被捕获。

int num = 1;
Converter<Integer, String> converter = (x) -> String.valueOf(x + num); 
num = 2; // 错误,num 不能被修改

这里 num 是 effectively final 变量,因为在 Lambda 创建后没被修改,所以也可以被捕获。但是如果修改 num 则会报错。

  1. 自由变量必须被隐式捕获,不能显式定义。
    例如:
int num = 1;
Converter<Integer, String> converter = (x) -> String.valueOf(x + num); 

这里 num 被隐式捕获,这是正确的。

int num = 1; 
Converter<Integer, String> converter = (x) -> { 
    int num = 2; 
    return String.valueOf(x + num); 
};

这里 num 被显式定义,这是错误的,因为与外部变量 num 同名,会产生隐藏的错误。

总之,Lambda 表达式可以捕获外部 final 或 effectively final 变量,使得 Lambda 表达式的行为可以与外部上下文紧密结合。但是也要注意变量捕获的要求,否则可能产生意料之外的错误。