网易首页 > 网易号 > 正文 申请入驻

为什么需要闭包?闭包是什么概念?

0
分享至

什么是闭包

闭包的英文对应的是Closure,如果要单纯的讨论这个概念的话就要提到和图灵机起名的大名鼎鼎的lambda演算(lamdba calculus)。尽管lamdba的概念并不是本文的重点,但是闭包概念的目的便是支持lamdba的实现。如果你单独地在百度对进行搜索闭包的话,你会发现大部分都是js相关的内容,主要是js本身就只用闭包的这个概念。但是闭包并不仅限于js,而是一个通用的概念。借用wiki中有点抽象的定义来说的话,闭包就是:

在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。

简单来说就是当一个方法引用了方法局部变量外的变量时,它就是一个闭包。而如果根据这个定义继续延展的话,就可以得到另外的一种描述方法:

闭包是由函数和与其相关的引用环境(方法外变量)组合而成的实体。

为什么需要闭包

尽管给出了两种关于闭包是什么的定义,但是闭包本身的概念还是较为的抽象。比如直接给例子,我们可以先讨论一下为什么需要闭包。

为了理解闭包,我们可以先假设这样的一种场景:

我有一个方法A,其中有私有变量。我想在别的方法中可以直接访问并使用它,但是又不想直接暴露它。

这时候,就可以在A建立一个内部类B来访问私有变量。那么这时候,这个内部类中你所可以访问B的方法,就和A中的私有变量形成了闭包。此时B已经捕获了A中的变量。即便是A对象销毁了,被B捕获的私有变量仍然不会释放。

所以可以理解,如果希望系统方法和当前环境的上下文绑定的话,就可以使用闭包。

尽管有些不恰当,但是我们可以再换一个实际的场景来举例子帮助你理解:

当你在购物的时候,你选中了一件商品,然后下单。这时候你的订单就已经绑定了你选中的商品。那么你的购买行为就和商品组成了闭包。这时候即便商家下架商品,也不会影响到商品后续的发货签收。并且这些逻辑只需要根据购买行为中的信息进行判断就可以了,而不用关心商家什么时候把商品下架,这写逻辑发生时候的商品价格是什么。

结合上面的例子,我们可以发现,当一个方法和其调用的外部环境形成闭包的时候,由于外部环境已经确定,那么我们就不用再关心外部环境了,而只用关心方法本身。

所以针对我们为什么需要闭包,我给出的答案是:

使用闭包的设计方式,由于闭包本身已经包含了上下文信息,所以可以对北向功能调用(用户)屏蔽由于环境而引发的复杂处理和交互成本。

Java中的闭包

对于Java来说,可以理解为主要是两种的闭包方式:

  • 内部类
  • lambda表达式

其中内部类除了本身的内部类还有局部内部类、匿名内部类。我们以最简洁的匿名内部类来举例:

  • public class Closure {
  • private int length = 0;
  • public ISay count() {
  • return new ISay() {
  • @Override
  • public void say(String message) {
  • length = message.length();
  • return "Talk:" + length;

此时say方法中便捕获了length属性,而如果你使用的是足够版本的IDE的话,获取还会提示你:

Anonymous new ISay() can be replaced with lambda

替换后:

  • public class Closure {
  • private int length = 0;
  • public ISay count() {
  • return message -> {
  • length = message.length();
  • return "Talk:" + length;

那么这时候你就会发现,此时return的对象就是一个通过匿名后直接描述的函数,而这个函数同时还关联了上下文之外的环境信息。

而在java8中lambda的中我们可以通过函数式编程接口直接接收这种闭包,这些接口常用的为:

  • Supplier
  • Predicate
  • Function

关于函数式接口本文就不展开了,但是利用函数式接口,我们就可以这样传递一个闭包:

  • public class Closure {
  • private int length = 0;
  • public Function
  • say() {
  • return message -> {
  • length = message.length();
  • return "Talk:" + length;

此时say返回的就不是String的结果了,而是直接将闭包本身返回了。而这个闭包在创建的时候就已经绑定了所需要的环境属性。所以我们可以在需要的时候再调用闭包,并且不用再关心它到底依赖了其他哪些变量:

  • public static void main(String[] args) {
  • final Function
  • say = new Closure().say();
  • System.out.println(say.apply("Something."));

当然你可能会角色,这个length似乎没有什么用呀,那如果我们换一个形式:

  • @Service
  • public class Closure {
  • @Resource
  • private HowtoSay howToSay;
  • public Function
  • say() {
  • return message -> {
  • return "Talk:" + howToSay.say(message);

使用Spring的依赖注入后,那么这个Closure类本身可能是各种策略模式策略器中的一个,策略器返回的是一个已经关联了具体策略路由的闭包。而当这个方法提供出去的时候,后续的调用者只需要知道这个闭包是可以针对文本进行处理的就可以,而至于之前是使用的什么策略它则不用关心。因为这些细节都已经通过闭包屏蔽了。

闭包的问题

仅仅谈论好的而对问题闭口不谈确实不好,虽然闭包提供了强大的功能,可以对业务细节进行屏蔽,对系统进行接耦拆分。但是闭包本身确实有一些问题需要留意:

  • 让对象的生命周期变长
  • 逻辑抽象

可以发现,这两个问题都是由于闭包本身的优点而产生的。由于闭包关联了环境信息,所以其让环境信息中对象的生命周期变长,这对于系统性能的维护以及jvm的垃圾回收都有负面因素。而同时因为不同于一般的编码风格,闭包的使用需要开发人员对实体进行抽象,才能比较好地实现。总结来说,对于开发人员本身有一定要求。

加餐

平时我们也经常使用lambda表达式来处理一些业务逻辑,偶尔会出现一下的情况:

  • interface Action
  • String doAction(String id);
  • public List
  • doAction(List
  • userIds){
  • List
  • result = new ArrayList<>();
  • for (int i = 0; i < 10; i++) {
  • result.add( id -> userIds.get(i)+"#");
  • return result;

先不管这段代码的实现业务背景是什么,但是IDE会提示在userIds.get(i)中的i提示的信息为:

Variable used in lambda expression should be final or effectively final

结合了上文中关于闭包的内容,我们就不难理解。由于闭包是要关联外部环境变量,在这部分代码中关联的是索引变量i,但是因为i本身是局部变量,无法保证关联环境的稳定性(我自己的理解),所以java编译器会强制的要求当闭包关联的是局部变量的时候,需要添加final关键字,而在进行final关键字从而保证该变量的内存引用不会发生改变。从本章的代码上结论上看则是进行了一次内存拷贝,来保证每个闭包中关联的环境变量不会改变,修改后的代码为:

  • public List
  • doAction(List
  • userIds){
  • List
  • result = new ArrayList<>();
  • for (int i = 0; i < 10; i++) {
  • int finalI = i;
  • result.add(id -> userIds.get(finalI)+"#");
  • return result;
最后

闭包本身是一种面向抽象编程,屏蔽细节的设计原则。在良好的设计下,可以通过闭包来屏蔽对于环境信息的感知,从而简化外部对于系统理解的成本,提高系统的易用性。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
凤凰卫视女主播称‘简体字比繁体字好用’引争议,港人留言:请入乡随俗

凤凰卫视女主播称‘简体字比繁体字好用’引争议,港人留言:请入乡随俗

TVB剧评社
2024-06-18 00:14:37
经济形势有多严峻?3个现象席卷中国各地,预示苦日子已开始?

经济形势有多严峻?3个现象席卷中国各地,预示苦日子已开始?

山丘楼评
2024-06-07 11:45:11
断供太惨了!来自广州的真实案例: 房子没了,还倒欠银行100万…

断供太惨了!来自广州的真实案例: 房子没了,还倒欠银行100万…

慧翔百科
2024-06-18 12:29:01
一直以为韩国很卷,没想到竟是瞎卷,被评论区笑发财了

一直以为韩国很卷,没想到竟是瞎卷,被评论区笑发财了

有趣的羊驼
2024-06-18 18:33:43
王思聪公开新女友身份,年轻漂亮比他小15岁,大量私照曝光很性感

王思聪公开新女友身份,年轻漂亮比他小15岁,大量私照曝光很性感

拾娱先生
2024-06-16 23:30:19
原价129,炒到6500!全国多地排队抢购,这一地玻璃门都“挤爆了”

原价129,炒到6500!全国多地排队抢购,这一地玻璃门都“挤爆了”

第一财经资讯
2024-06-17 20:51:06
学会了!吉林男子趁着女朋友上厕所时求婚:不答应也得答应

学会了!吉林男子趁着女朋友上厕所时求婚:不答应也得答应

唐小糖说情感
2024-06-18 17:33:33
河南叶县冷藏车惨祸,亲属:8人都是女工,每天上下班都坐冷藏车,疑因车厢内干冰泄露,司机最高或判7年

河南叶县冷藏车惨祸,亲属:8人都是女工,每天上下班都坐冷藏车,疑因车厢内干冰泄露,司机最高或判7年

纵相新闻
2024-06-17 22:15:35
高温袭袭,让电动车“沦为笑柄”,彻底取代燃油车还是一句空话

高温袭袭,让电动车“沦为笑柄”,彻底取代燃油车还是一句空话

户外小阿隋
2024-06-18 14:48:39
最新战报!4-6,中国莎娃告急,1姐郑钦文双重喜,1成就历史前10

最新战报!4-6,中国莎娃告急,1姐郑钦文双重喜,1成就历史前10

刘姚尧的文字城堡
2024-06-19 06:08:14
抗美援朝的骗局,美国珍藏41年的情报公开,才知道原来是我军圈套

抗美援朝的骗局,美国珍藏41年的情报公开,才知道原来是我军圈套

为什么有冬天夏天
2024-06-19 00:28:05
新型卖淫方式,让人预想不到,但却真实存在!

新型卖淫方式,让人预想不到,但却真实存在!

雪影的情感
2023-11-18 11:51:16
上海已婚少妇“脚踏四只船”,出轨全过程曝光,传疯了!

上海已婚少妇“脚踏四只船”,出轨全过程曝光,传疯了!

拾点先生
2024-06-17 20:14:40
有一种痛苦叫选了“一梯两户”,卖不出也不想住,彻底成为不动产

有一种痛苦叫选了“一梯两户”,卖不出也不想住,彻底成为不动产

平说财经
2024-06-18 16:19:37
刁琳宇:出身农村,争议中走来的中国女排主二传,30岁有男友吗?

刁琳宇:出身农村,争议中走来的中国女排主二传,30岁有男友吗?

细品名人
2024-06-19 07:45:48
女孩子为什么喜欢被打屁股?她的快乐你想象不到

女孩子为什么喜欢被打屁股?她的快乐你想象不到

南风山
2024-06-18 01:45:02
表面人模人样,实则是流氓头子,家暴恶魔,这6位男星太令人作呕

表面人模人样,实则是流氓头子,家暴恶魔,这6位男星太令人作呕

蜉蝣说
2024-06-17 22:30:51
创纪录!网约车司机被乘客殴打获赔26万!

创纪录!网约车司机被乘客殴打获赔26万!

网约车观察室
2024-06-18 11:35:52
有种球员失去后才追悔莫及,他的名字叫霍勒迪

有种球员失去后才追悔莫及,他的名字叫霍勒迪

澎湃新闻
2024-06-19 10:04:34
《玫瑰的故事》播出一半后才发现,刘亦菲根本不是天选的“玫瑰”

《玫瑰的故事》播出一半后才发现,刘亦菲根本不是天选的“玫瑰”

兰子记
2024-06-15 20:36:41
2024-06-19 10:52:49
蜜糖的代码注释
蜜糖的代码注释
记录技术成长。
32文章数 29关注度
往期回顾 全部

科技要闻

英伟达市值超微软 成全球市值最高上市公司

头条要闻

网友称北京科技大学教授看望姜萍 校方:非本校老师

头条要闻

网友称北京科技大学教授看望姜萍 校方:非本校老师

体育要闻

幸运的倒霉蛋!8年前差点退役,现在他帮两支NBA球队夺冠

娱乐要闻

黄一鸣“杀疯了” 直播间卖大葱养孩子

财经要闻

吴清:证监会将推出“科创板八条”

汽车要闻

全球最低价 现代IONIQ 5N预售价39.88万

态度原创

教育
房产
时尚
本地
公开课

教育要闻

【#北大博士挑战姜萍竞赛题7题仅对1道#】#你认为天赋和努力哪个更重要# 近日,17岁的中专在读生姜...

房产要闻

17.9亿!终于,有民企在三亚大手笔拿地了!周边房价10万+!

会戴帽子的女人真是优雅,就像赫本那样!

本地新闻

我和我的家乡|在鞍山的每一步都有新发现

公开课

近视只是视力差?小心并发症

无障碍浏览 进入关怀版