由于 scala 中函数内部能定义函数, 且函数能作为函数的返回值, 那么问题来了, 当返回的函数使用了外层函数的局部变量时, 会发生什么呢? 没错, 就产生是闭包.
关于闭包的解释网上一大堆, 但基本上都是照葫芦画瓢, 一个模子刻出来的, 说来说去都只讲了 "内部函数引用外层函数的局部变量" 这个刻板的定义, 根本没降到精髓. 精髓是什么? 且看我一句话给你讲清楚:
闭包就是外层函数函数的对象, 外层函数就是闭包的构造函数!
怎么样, 是不是摸不着头脑? 其实是这样, 我们使用闭包的目的并不是为了引用外层函数的局部变量, 这只是手段, 不是目的; 我们的最终目的其实是函数的定制化, 即按照一定的模板根据输出生成具有不同功能的函数, 其实就是 "函数的函数". 这里我们马上可以想到, 就相当于 "类" 的思想, 能根据不同的构造函数产生不同的 "类的对象". 其实这里就是利用了这种思路, 把外层函数当做构造函数, 利用传入的参数进行定制, 生成具有不同功能的函数并返回.
道理我都懂, 但这跟 "引用局部变量" 有什么关系? 很简单呀, 比方说外层函数就是一个毛坯房, 返回的函数时精装修房, 那么外层函数的参数是装修图纸, 最终得到的房子肯定是要用到这个图纸或者图纸的衍生物的, 因此为了实现定制化, 很定要依靠于外层函数的局部变量.
但是这里有个问题: 我们都知道, 正常来说函数的局部变量是存储在栈内存的, 而对象是存储在堆内存的, 因此同一个类可能存在多个对象, 而函数在执行完成之后栈内存就会释放, 因此不会存在多份函数的局部变量. 但是根据我们上边的分析, 定制化的函数肯定是要用到局部变量的, 而且不同的定制化肯定是要保存多份局部变量, 且相互之间空间独立的, 就如同不同的对象一样. 那么 scala 是怎么解决这个问题的呢? 根据这篇文章 https://www.jianshu.com/p/8f24150fad2a 的介绍, scala 在生成闭包时使用了一个临时对象来保存外层函数中的局部变量, 因此可以算是将当前堆内存中的变量拷贝了一份到栈内存中, 因此实现了多份局部空间的并存, 以及函数闭包.
来源: https://www.cnblogs.com/wangyalou/p/9601939.html