热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java中闭包的争论以及闭包的定义和特性

闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。

点击关注程序员港湾,每天给你一点成长

闭包一直都是Java社区中争论不断的话题,很多语言例如Javascript,RubyPython等都支持闭包这个语言特性,闭包功能强大且灵活,并没有显式地支持它,但其实中也存在着所谓的”闭包”.

闭包

定义一个闭包的要点如下:

一个依赖于外部环境的自由变量的函数.

这个函数能够访问外部环境的.

也就是说,外部环境持有内部函数所依赖的 自由变量 ,由此对内部函数形成了闭包.

自由变量

那么什么是自由变量呢?自由变量 就是在函数自身作用域之外的变量,一个函数f(x)=x+y" tabindex="0" class="MathJax"> f ( x ) = x + y,其中y就是,它并不是这个函数自身的自变量,而是通过外部环境提供的.

下面以Javascript的一个闭包为例:

1

2

3

4

5

function Add ( y ){

returnfunction ( x )

x + y;

}

对于内部函数function(x)来说,.而是函数Add(y)内的参数,所以对内部函数形成了一个闭包.

这个闭包将自由变量y与内部函数绑定在了一起,也就是说,当函数执行完毕后,它不会随着函数调用结束后被回收(不能在栈上分配空间).

varadd_function = Add(5);// 这时y=5,并且与返回的内部函数绑定在了一起

result = add_function(10// x=10,返回最终的结果 10 + 5 = 15

Java中的闭包

Java与又或者其他支持闭包的语言不同,它是一个基于类的面向对象语言,也就是说一个方法所用到的 自由变量 永远都来自于其所在类的实例的.

6

7

class AddUtils

privateinty =;

public int add ( int x)

retrun x + y;

这样一个方法add(x)拥有一个参数x与一个,它的返回值也依赖于这个.想要正常工作的话,就必须依赖于AddUtils类的一个实例,不然它无法知道的值是多少,也就是未与进行绑定.

严格上来说,中的应该为this,这是因为也是通过关键字来访问的.

所以说,在中闭包其实无处不在,只不过我们难以发现而已.但面向对象的语言一般都不把类叫成闭包,这是一种习惯.

中的内部类就是一种典型的闭包结构.

8

9

10

11

12

publicclass Outer

class Inner

x =

public int add ()

内部类通过一个指向外部类的引用来访问外部环境中的,由此形成了一个闭包.

匿名内部类

13

14

15

16

public interface AnonInner ()

int add ()

public AnonInner getAnonInner ( final int x)

final

newAnonInner() {

getAnonInner(x)方法返回了一个匿名内部类AnonInner,匿名内部类不能显式地声明构造函数,也不能对构造函数传参,且返回的是一个接口,但它的add()方法实现中用到了两个(),也就是说外部方法对这个匿名内部类构成了闭包.

但我们发现都被加上了final修饰符,这是因为对闭包支持的不完整导致的.

对于的捕获策略有以下两种:

capture-by-value: 只需要在创建闭包的地方把捕获的值拷贝一份到对象里即可.Java的匿名内部类和Java 8新的lambda表达式都是这样实现的.

capture-by-reference: 把被捕获的局部变量“提升”(hoist)到对象里.C#的匿名函数(匿名委托/lambda表达式)就是这样实现的.

只实现了capture-by-value,但又没有对外说明这一点,为了以后能进一步扩展成支持capture-by-reference留后路,所以干脆就不允许向被捕获的变量赋值,所以这些需要强制加上修饰符(在Jdk8中似乎已经没有这种强制限制了).

作者: SylvanasSun

源自:https://sylvanassun.github.io/2017/07/30/2017-07-30-JavaClosure/

声明:文章著作权归作者所有,如有侵权,请联系小编删除。

感谢 · 转发 欢迎大家留言



推荐阅读
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文介绍了如何利用JavaScript或jQuery来判断网页中的文本框是否处于焦点状态,以及如何检测鼠标是否悬停在指定的HTML元素上。 ... [详细]
  • Java 类成员初始化顺序与数组创建
    本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
author-avatar
isme7
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有