当前位置:首页 > wifi设置知识 > 正文内容

闭包是什么概念,先检查下这些地方

秋天2024年01月22日 18:01:55wifi设置知识84
如果您是路由器的新手用户,本文闭包是什么概念 将为您提供适用于不同品牌和型号的路由器设置方法和技巧。

什么是闭包

闭包的英文对应的是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的中我们可以通过函数式编程接口直接接收这种闭包,这些接口常用的为:

SupplierPredicateFunction

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

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; }

最后

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

~不管您是在家里还是在办公室,这些技巧都可以帮助您更好地管理您的网络连接。

扫描二维码推送至手机访问。

版权声明:本文由路由设置网发布,如需转载请注明出处。

本文链接:https://www.shoulian.org/luyou/post/141567.html

分享给朋友:

“闭包是什么概念,先检查下这些地方” 的相关文章

路由器电缆断开怎么解决

路由器电缆断开怎么解决

当朋友们看到这个文章时想必是想要了解路由器电缆断开怎么解决相关的知识,这里同时多从个角度为大家介绍路由器网络连接断开如何解决相应的内容。 本文内容目录一览: 1、访问点 路由器或电缆调制解调器与Internet之间的连接断开怎么弄啊 上不到网 2、家里的路由器怎么老是断开连接啊,怎么解决啊?...

怎么关千兆路由器网

怎么关千兆路由器网

今天和朋友们分享怎么关千兆路由器网相关的知识,相信大家通过本文介绍也能对怎么关千兆路由器网络有自已的收获和理解。自己轻松搞问题。本文内容目录一览: 1、千兆路由器应该怎么设置 2、千兆路由器跟无线路由器怎么设置 3、双频千兆无线路由器2.4g网络怎么限制上网 4、路由器怎么关闭wifi...

怎么查找本机路由器ip

怎么查找本机路由器ip

当朋友们看到这个文章时想必是想要了解怎么查找本机路由器ip相关的知识,这里同时多从个角度为大家介绍路由器如何找到主机相应的内容。 本文内容目录一览: 1、如何查路由器网络地址 2、路由器ip地址怎么看 3、怎样查找路由器的IP地址? 4、怎么查找路由器ip地址 5、怎么查路由器本机I...

路由器更好IP怎么设置

路由器更好IP怎么设置

针对路由器更好IP怎么设置这个问题,本文将综合不同朋友对这个如何设置路由器IP的知识为大家一起来解答,希望能帮到大家 本文内容目录一览: 1、路由器的ip的设置方法 2、怎么正确设置路由器ip 3、路由器ip地址怎么设置 4、路由器ip怎么设置 5、路由器怎么设置ip配置 6、无...

路由器怎么连wo光线

路由器怎么连wo光线

今天给各位分享路由器怎么连wo光线的知识,其中也会对路由器怎么连wifi开wifi进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站 本文内容目录一览: 1、路由器怎么连wifi? 2、wo-37型光猫怎么连路由器 3、联通光猫wo27s如何连接路由器? 4、路由器怎么连接WLAN...

路由器跟宽带怎么设置

路由器跟宽带怎么设置

针对路由器跟宽带怎么设置这个问题,本文将综合不同朋友对这个路由器跟宽带怎么设置连接的知识为大家一起来解答,希望能帮到大家 本文内容目录一览: 1、无线路由器插宽带网线,如何设置 2、路由器连接宽带怎么设置 3、家里宽带连接上网的,路由器怎么设置 4、电信宽带设置路由器怎么设置? 无线路...