「java有闭包吗」java封闭实例是什么
本篇文章给大家谈谈java有闭包吗,以及java封闭实例是什么对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、java中的闭包到底是什么意思啊???
- 2、JAVA 需要引入闭包吗
- 3、北大青鸟java培训:js解析机制与闭包分析?
- 4、java里面的闭包和反射是什么东西?
- 5、为什么需要闭包?闭包是什么概念?
java中的闭包到底是什么意思啊???
闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建他的作用域,用过这个定义 可以看出内部类是面向对象的闭包 因为他不仅包含外围类对象的信息 还自动拥有一个指向此外围类对象的引用 在此作用域内 内部类有权操作所有的成员 包括private成员;interface Incrementable
{
void increment();
} class Callee1 implements Incrementable
{
private int i=0;
public void increment()
{
i++;
System.out.println(i);
}
}class MyIncrement
{
void increment()
{
System.out.println("other increment");
}
static void f(MyIncrement mi)
{
mi.increment();
}
}class Callee2 extends MyIncrement
{
private int i=0;
private void incr()
{
i++;
System.out.println(i);
}
private class Closure implements Incrementable
{
public void increment()
{
incr();
}
}
Incrementable getCallbackReference()
{
return new Closure();
}
}
class Caller
{
private Incrementable callbackRefference;
Caller(Incrementable cbh)
{
callbackRefference = cbh;
}
void go()
{
callbackRefference.increment();
}
}public class Callbacks
{
public static void main(String [] args)
{
Callee1 c1=new Callee1();
Callee2 c2=new Callee2();
MyIncrement.f(c2);
Caller caller1 =new Caller(c1);
Caller caller2=new Caller(c2.getCallbackReference());
caller1.go();
caller1.go();
caller2.go();
caller2.go();
}
}输出other increment
1
2
1
2Callee2继承字MyIncrement 后者已经有一个不同的increment()方法并且与Incrementable接口期望的increment()方法完全不相关 所以如果Callee2继承了MyIncrement就不能为了Incrementable的用途而覆盖increment()方法 于是这能使用内部类独立的实现Incrementable内部类Closure实现了Incrementable 一提供一个放回Caller2的钩子 而且是一个安全的钩子 无论谁获得此Incrementbale的引用 都只能调用increment() 除此之外没有其他功能
JAVA 需要引入闭包吗
那么JAVA(有了对象)还需要引入闭包吗?
我觉得不需要,
因为对象完全可以模拟
闭包
的行为,
而且
对象
才是
OOP
的
一级元素。
闭包
是
函数式编程(FP)
中的
概念,
引入闭包
就相当于
引入
FP,
这只会破坏
JAVA
的
纯粹
与
简单
。。
北大青鸟java培训:js解析机制与闭包分析?
随着互联网的不断发展,程序员在学习JavaScript编程开发上也有了更多的了解,今天我们就简单分析一下关于JavaScript编程解析机制以及闭包的一些常见问题。
js解析机制:js代码解析之前会创建一个如下的词法环境对象(仓库):LexicalEnvironment{}在扫描js代码时会把:1、用声明的方式创建的函数的名字;2、用var定义的变量的名字存到这个词法环境中;3、同名的时候:函数声明会覆盖变量,下面的函数声明会覆盖上面的同名函数;4、函数的值为:对函数的一个引用;变量的值为undefined;5、如果用函数表达式的方式创建一个函数:varfn=function(){}这样词法环境中存的是一个变量名fn,并赋值为undefined;在调用函数的时候如果在函数上面调用就会出现和变量一样的情况报错undefined;这也是以两种不同方式创建函数的区别;闭包:定义:(有多种定义)1、(比较通俗的定义):函数嵌套函数,内部函数可以引用外部函数的参数和变量,这些参数和变量不会被垃圾回收机制所回收;2、在计算机科学中,闭包是词法闭包的简称,是引用了自由变量的函数,这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外(意思就是不会被销毁)。
3、闭包是由函数和其相关的引用环境组合而成的实体。
(潜台词就是这个函数将和引用环境同时存在,必须有引用)综合来说,不管怎么定义都是在围绕着两个本质:函数在引用变量,这个变量将不会被销毁。
闭包的一个作用就是:我们能够通过闭包的方法来在外部访问到一个内部函数的变量;很多人在解释闭包的时候都会把子函数return出去以后在外部调用,其实无论在哪里调用,闭包都已经形成了,只要是函数嵌套函数,并且子函数引用了父函数的变量,(不论子函数有没有被调用,电脑培训认为这个用一种方法证明:在子函数内部打断点,在f12中观察闭包里的内容,已经出现了引用函数,这时候调用还没有被执行)这个时候闭包已经形成了。
java里面的闭包和反射是什么东西?
反射不知道,闭包就是在函数中返回函数的技术吧
var f = function(){
var i=1;
return function ft(){
return i++;}
}
这是实现计数的,在c语言中很简单,在函数中声明static就好了,每次调用值不会重置,有些语言没有这个概念,把计数变量放在全局虽然能实现计数但是不安全,放在函数类的话 每次调用就会被重置,
此时就要利用全局不能访问局部变量的特点,把函数放在一个匿名函数内部,内部函数可以访问外部函数的i变量,外部函数的变量只会初始化一次,调用ft函数就能实现计数,这个流程就叫闭包
为什么需要闭包?闭包是什么概念?
闭包的英文对应的是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来说,可以理解为主要是两种的闭包方式:
其中内部类除了本身的内部类还有局部内部类、匿名内部类。我们以最简洁的匿名内部类来举例:
此时say方法中便捕获了length属性,而如果你使用的是足够版本的IDE的话,获取还会提示你:
Anonymous new ISay() can be replaced with lambda
替换后:
那么这时候你就会发现,此时return的对象就是一个通过匿名后直接描述的函数,而这个函数同时还关联了上下文之外的环境信息。
而在java8中lambda的中我们可以通过函数式编程接口直接接收这种闭包,这些接口常用的为:
关于函数式接口本文就不展开了,但是利用函数式接口,我们就可以这样传递一个闭包:
此时say返回的就不是String的结果了,而是直接将闭包本身返回了。而这个闭包在创建的时候就已经绑定了所需要的环境属性。所以我们可以在需要的时候再调用闭包,并且不用再关心它到底依赖了其他哪些变量:
当然你可能会角色,这个length似乎没有什么用呀,那如果我们换一个形式:
使用Spring的依赖注入后,那么这个Closure类本身可能是各种策略模式策略器中的一个,策略器返回的是一个已经关联了具体策略路由的闭包。而当这个方法提供出去的时候,后续的调用者只需要知道这个闭包是可以针对文本进行处理的就可以,而至于之前是使用的什么策略它则不用关心。因为这些细节都已经通过闭包屏蔽了。
仅仅谈论好的而对问题闭口不谈确实不好,虽然闭包提供了强大的功能,可以对业务细节进行屏蔽,对系统进行接耦拆分。但是闭包本身确实有一些问题需要留意:
可以发现,这两个问题都是由于闭包本身的优点而产生的。由于闭包关联了环境信息,所以其让环境信息中对象的生命周期变长,这对于系统性能的维护以及jvm的垃圾回收都有负面因素。而同时因为不同于一般的编码风格,闭包的使用需要开发人员对实体进行抽象,才能比较好地实现。总结来说,对于开发人员本身有一定要求。
平时我们也经常使用lambda表达式来处理一些业务逻辑,偶尔会出现一下的情况:
先不管这段代码的实现业务背景是什么,但是IDE会提示在userIds.get(i)中的i提示的信息为:
Variable used in lambda expression should be final or effectively final
结合了上文中关于闭包的内容,我们就不难理解。由于闭包是要关联外部环境变量,在这部分代码中关联的是索引变量i,但是因为i本身是局部变量,无法保证关联环境的稳定性(我自己的理解),所以java编译器会强制的要求当闭包关联的是局部变量的时候,需要添加final关键字,而在进行final关键字从而保证该变量的内存引用不会发生改变。从本章的代码上结论上看则是进行了一次内存拷贝,来保证每个闭包中关联的环境变量不会改变,修改后的代码为:
闭包本身是一种面向抽象编程,屏蔽细节的设计原则。在良好的设计下,可以通过闭包来屏蔽对于环境信息的感知,从而简化外部对于系统理解的成本,提高系统的易用性。
关于java有闭包吗和java封闭实例是什么的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
发布于:2022-12-13,除非注明,否则均为
原创文章,转载请注明出处。