为什么说 java 中 lambda 表达式的闭包是伪闭包?

探讨Java中Lambda表达式为何被称为伪闭包,解释其依赖于参数和常量而非外部变量的特性,以及Java如何通过final或effectively final解决局部变量引用问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么说 java 中 lambda 表达式的闭包是伪闭包?

Lambda 表达式不依赖于任何外部实体;它们是依赖于自身参数和常量的内容。

public interface calculator{
    int calculate(int a);
}

calculator cal = (x)->2*x;
cal.calculate(5);
复制代码

闭包既依赖于参数和常量,也依赖于它们的词法范围中的变量。

public interface Calculator{
    int calculate(int a);
}

int i = 2;
calculator cal = (x)->x*i;
cal.calculate(5);
复制代码

在Java中,以上两者的概念都被认为是java中的lambda表达式。

在 jdk1.7 中第二个例子中的如果内部类用到了局部变量 i 如果并且不设置为 final 会报编译错误。而在java8 中的语法糖解决了这一点。那我们修改自由变量 i 的值能否通过编译呢。

public interface Calculator{
    int calculate(int a);
}

int i = 2;
calculator cal = (x)->x*i;
i++;
cal.calculate(5);
复制代码

结果是编译失败了,编译器报出了如下错误。

Variable used in lambda expression should be final or effectively final
复制代码

final 指的是显式得将 i 声明成 final 变量,effectively final 指的是在代码中可以不显式得指明 final 但是你却不能改变他。由此可见 java 8 中只是增加了语法糖,lambda 表达式或者是内部类中仍然不能改变自由变量。

从编译器的角度来看,以上代码其实是被编译成了

class TestClass$1
        implements Calculator {
    private final TestClass this$0;
    private final Integer paramInteger;

    TestClass$1
    (TestClass this$0, Integer paramInteger) {
        this.this$0 = this$0;
        this.paramInteger = paramInteger;
    }

    public Integer calculate(Integer a) {
        return a * this.paramInteger;
    }
}
复制代码

i 被作为成员变量传入了编译出的匿名类,因此不管在外部还是内部改变了 i 的值都没有办法影响彼此的值。

从理解角度来看,在代码层面内外部的 i 看上去就是同一个变量,改动彼此都应该生效。但其实不行,因此「 Variable used in lambda expression should be final or effectively final 」。

而在闭包的意义上来看,为了维护自由变量在 lambda 表达式中和外部保持同一状态,既然改变值无法影响状态,干脆就规定只能 final 好了。

因此 java 8 中 lambda 表达式支持的闭包被诟病为一种伪闭包。

参考 [1]: www.zhihu.com/question/24… "闭包(计算机科学)是什么?" [2]: cuipengfei.me/blog/2013/0… "为什么必须是final的呢?" [3]: www.javaworld.com/article/209… "Java programming with lambda expressions" [4]: www.ibm.com/developerwo… "使用闭包捕获状态"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值