0%

什么是闭包

定义

闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。

两个概念

  • 自变量
  • 自由变量

javascript的闭包

function Add(y) {
return function(x) {
return x + y
}
}

其中x是自变量,y是自由变量

java中的闭包

public void bindViewHolder(View view, find int position) {
view.setOnClickListener(new OnClickListener {
// 这里使用了外部的position自由变量,就是闭包
Item item = list.get(position)
})
}

java为什么匿名内部类的参数引用时final?

内部类可以通过外部类的引用拿到外部类自由变量的值,但是没法通过引用获取函数参数,函数成员等这些自由变量。
所以Java编译器把这些自由变量的值偷偷拷贝了一份放在了内部类中。
所以为了保持两个成员的值一致,Java就用final规定这个值不能改变。

这是java特有的,其他的语言不会这样,其他的语言会依然对象的传递引用进入内部类

这些变量的生命周期:

因为每个内部类的实例都隐藏了一个指向外部类实例的引用。java只是没有显式地写出来而已。内部类访问外部类成员都是透过这个引用。之所以能有这个引用,是因为两者都是实例,都有自己的内存空间。而匿名内部类的外围环境函数只是一个函数,执行完之后,也就是匿名内部类诞生(初始化)完成的那一刻,它的生存周期就结束了。函数内部的局部变量(包括函数的参数)也就跟着被销毁了。所以产生出来的内部类根本无法像保留外部类的引用那样保留外围环境函数的引用。所以只能退而求其次,只保留一份局部变量的拷贝值。

一个函数的成员变量在函数执行完之后必须销毁,是因为执行函数的内存开销是在栈上。每执行一个函数,都会在栈上压一个新的栈帧,函数的局部变量,包括参数都存在这个栈帧的局部变量表里。函数执行完之后,根据栈的LIFO顺序,当前栈帧就被从栈上弹出销毁。内存上就没有这个函数的痕迹了。

参考