博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lambda表达式和闭包
阅读量:7254 次
发布时间:2019-06-29

本文共 1670 字,大约阅读时间需要 5 分钟。

区分lambda表达式和闭包

熟悉的Javascript或者Ruby的同学,可能对另一个名词:闭包更加熟悉。因为一般闭包的示例代码,长得跟lambda差不多,导致我也在以前很长一段时间对这两个概念傻傻分不清楚。其实呢,这两个概念是完全不同维度的东西。

闭包是个什么东西呢?我觉得Ruby之父松本行弘在《代码的未来》一书中解释的最好:闭包就是把函数以及变量包起来,使得变量的生存周期延长。闭包跟面向对象是一棵树上的两条枝,实现的功能是等价的。

这样说可能不够直观,我们还是用代码说话吧。其实Java在很早的版本就支持闭包了,只是因为应用场景太少,这个概念一直没得到推广。在Java6里,我们可以这样写:

public static Supplier
testClosure(){ final int i = 1; return new Supplier
() { @Override public Integer get() { return i; } };}public interface Supplier
{ T get();}

看出问题了么?这里i是函数testClosure的内部变量,但是最终返回里的匿名对象里,仍然返回了i。我们知道,函数的局部变量,其作用域仅限于函数内部,在函数结束时,就应该是不可见状态,而闭包则将i的生存周期延长了,并且使得变量可以被外部函数所引用。这就是闭包了。这里,其实我们的lambda表达式还没有出现呢!

而支持lambda表达式的语言,一般也会附带着支持闭包了,因为lambda总归在函数内部,与函数局部变量属于同一语句块,如果不让它引用局部变量,不会让人很别扭么?例如Python的lambda定义我觉得是最符合λ算子的形式的,我们可以这样定义lambda:

#!/usr/bin/pythony = 1f=lambda x: x + yprint f(2)y = 3print f(2)输出: 35

 

这里y其实是外部变量。

Java中闭包带来的问题

在Java的经典著作《》、《》里,大神们都提到:匿名函数里的变量引用,也叫做变量引用泄露,会导致线程安全问题,因此在Java8之前,如果在匿名类内部引用函数局部变量,必须将其声明为final,即不可变对象。(Python和Javascript从一开始就是为单线程而生的语言,一般也不会考虑这样的问题,所以它的外部变量是可以任意修改的)。

在Java8里,有了一些改动,现在我们可以这样写lambda或者匿名类了:

public static Supplier
testClosure() { int i = 1; return () -> { return i; };}

这里我们不用写final了!但是,Java大神们说的引用泄露怎么办呢?其实呢,本质没有变,只是Java8这里加了一个语法糖:在lambda表达式以及匿名类内部,如果引用某局部变量,则直接将其视为final。我们直接看一段代码吧:

public static Supplier
testClosure() { int i = 1; i++; return () -> { return i; //这里会出现编译错误 };}

明白了么?其实这里我们仅仅是省去了变量的final定义,这里i会强制被理解成final类型。很搞笑的是编译错误出现在lambda表达式内部引用i的地方,而不是改变变量值的i++…这也是Java的lambda的一个被人诟病的地方。我只能说,强制闭包里变量必须为final,出于严谨性我还可以接受,但是这个语法糖有点酸酸的感觉,还不如强制写final呢…

 

转载于:https://www.cnblogs.com/UncleWang001/p/9829597.html

你可能感兴趣的文章
Android -- Webview自适应屏幕
查看>>
从Delphi 7升级到Delphi XE
查看>>
android圆形图像
查看>>
Oracle数据库备份还原工具之Expdp/IMPdp
查看>>
【转】android JNI编程 一些技巧(整理)
查看>>
MySQL之终端(Terminal)管理数据库、数据表、数据的基本操作
查看>>
各种排序算法汇总
查看>>
C#巧用Excel模版变成把Table打印出来
查看>>
SOAP 及其安全控制--转载
查看>>
JarSearch
查看>>
[Unity3D][Vuforia][IOS]vuforia在unity3d中添加自己的动态模型,识别自己的图片,添加GUI,播放视频...
查看>>
Freemodbus介绍及测试
查看>>
[转]Phantomjs实现获取网页快照并生成缩略图
查看>>
leveldb源码学习系列
查看>>
Linux 运行 apt-get install 就出现jdk installer 错误的解决方法
查看>>
Android OpenGL ES(九)绘制线段Line Segment .
查看>>
Ubuntu下安装配置JDK1.7
查看>>
转载:STM32之中断与事件---中断与事件的区别
查看>>
[裴礼文数学分析中的典型问题与方法习题参考解答]4.5.10
查看>>
设计模式(十四)单例模式(创建型)
查看>>