• 念念不忘,必有回响!包含: Java 基础, Java 部分源码, JVM, Spring, Spring Boot, Spring Cloud, 开源项目等
  • 念念不忘,必有回响!包含: 数据库原理, MySQL, ElasticSearch, MongoDB, Docker,CI&CD, Linux, DevOps, 分布式, 中间件等
  • 念念不忘,必有回响!包含: 开发工具, Git, IDE, 源码阅读,读书笔记等

Lambda作用范围

2023-04-15 11:14
3216
0

Accessing outer scope variables from lambda expressions is very similar to anonymous objects. You can access final variables from the local outer scope as well as instance fields and static variables.

Lambda表达式访问外部的变量(局部变量,成员变量,静态变量,接口的默认方法),它与匿名内部类访问外部变量非常相似。

#1. 访问局部变量

我们可以从lambda表达式的外部范围读取最终局部变量num;

int num = 1;
IConverter<Integer, String> stringConverter = from -> String.valueOf(from + num);
String convert = stringConverter.convert(2);
System.out.println(convert); // 3
    @小傅哥: 代码已经复制到剪贴板

但是这个num是不可变值,这样改变值会报错;

int num = 1;
IConverter<Integer, String> stringConverter =
        (from) -> String.valueOf(from + num);
num = 3;
    @小傅哥: 代码已经复制到剪贴板

Variable used in lambda expression should be final or effectively final

另外在lambda表达式内部修改也是不允许的;

int num = 1;
IConverter<Integer, String> converter = (from) -> {
    String value = String.valueOf(from + num);
    num = 3;
    return value;
};
    @小傅哥: 代码已经复制到剪贴板

Variable used in lambda expression should be final or effectively final

#2. 访问成员变量和静态变量

在 Lambda 表达式中访问局部变量。与局部变量相比,在 Lambda 表达式中对成员变量和静态变量拥有读写权限:

public class Lambda4 {
// 静态变量
static int outerStaticNum;
// 成员变量
int outerNum;

void testScopes() {
    IConverter&lt;Integer, String&gt; stringConverter1 = (from) -&gt; {
        // 对成员变量赋值
        outerNum = 23;
        return String.valueOf(from);
    };

    IConverter&lt;Integer, String&gt; stringConverter2 = (from) -&gt; {
        // 对静态变量赋值
        outerStaticNum = 72;
        return String.valueOf(from);
    };
}

}

    @小傅哥: 代码已经复制到剪贴板

#3. 访问默认接口方法

还记得第一节的IFormula示例吗?

public interface IFormula {
double calculate(int a);

// 平方
default double sqrt(int a) {
    return Math.sqrt(a);
}

}

    @小傅哥: 代码已经复制到剪贴板

当时,我们在接口中定义了一个带有默认实现的 sqrt 求平方根方法,在匿名内部类中我们可以很方便的访问此方法:

IFormula formula = new IFormula() {
    @Override
    public double calculate(int a) {
        return a * a;
    }
};
    @小傅哥: 代码已经复制到剪贴板

但是不能通过lambda表达式访问默认方法,这样的代码没法通过编译;

IFormula formula = (a) -> sqrt(a * a);
    @小傅哥: 代码已经复制到剪贴板

带有默认实现的接口方法,是不能在 lambda 表达式中访问的,上面这段代码将无法被编译通过。

全部评论