Lambda 表达式可以捕获外部变量。但是,有以下几点要求:
- 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 则会报错。
- 自由变量必须被隐式捕获,不能显式定义。
例如:
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 表达式的行为可以与外部上下文紧密结合。但是也要注意变量捕获的要求,否则可能产生意料之外的错误。