美文网首页
java的闭包

java的闭包

作者: 船_长 | 来源:发表于2020-07-06 20:07 被阅读0次

什么是闭包

1、一个含有自由变量的函数;
2、这些自由变量所在的环境。
也就是函数和环境的总和构成一个闭包。外部环境持有内部函数所使用的自由变量,对内部函数形成“闭包”。
简单但不严格的说,一个函数的“自由变量”就是既不是参数也不是局部变量的变量(外部变量)。

一个纯粹(无副作用)的函数如果不含有自由变量,那么每次用相同的参数调用后的得到的结果肯定是一样的。但如果一个函数含有自由变量,那么调用返回的结果不但依赖于参数的值,还依赖于自由变量的值。因此一个含有自由变量的函数要正确执行,必须保证其所依赖的外围环境的存在。
在JS中的样子如下

function a() { 
  var i = 0; 
  function b() { alert(++i); } 
  return b; 
} 
var c = a(); 
c();      //1 
c();      //2 

闭包和面向对象

闭包与对象是从两个完全不同的角度描述了一件事情:一段代码与其环境的关系。
所以可以用对象来模拟(实现)闭包,也可以用闭包来模拟(实现)对象。
刚刚闭包里的例子的效果完全可以用对象做出来, 这两种方式都体现了函数和环境之间的关系。

class a {  
    private int i = 0;  
    int b( ) { System.out.priintly(++i); }  
}  
a c = new a();
c.b //1
c.b //2

当然严格来说方法所捕获的自由变量不是i,而是this;i是通过this来访问到的,完整写出应该是this.i。

闭包的传值

让我们考察下面两种情况:

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

  • 有引用捕获(capture-by-reference):把被捕获的局部变量“提升”(hoist)到对象里。C#的匿名函数(匿名委托/lambda表达式)就是这样实现的。参考Eric Lippert大神对“hoist”一词的讲解。不要把这个“hoist”的用法跟JavaScript里说的把局部变量提前到函数开头来声明的那种用法混为一谈。

如果变量(variable)是不可变(immutable)的,那么使用者无法感知值捕获和引用捕获的区别。

  • 有些语言(例如C++11)允许显式指定捕获列表以及捕获方式(值捕获还是引用捕获),这样最清晰,不过写起来比较长;
  • 有些语言(例如JavaScript)只有引用捕获,要模拟值捕获的效果需要手动新建闭包和局部变量;有些语言(例如C#)对不可变量(const local)做值捕获,对普通局部变量做引用捕获;由于无法感知对不可变量的值捕获与引用捕获的区别,统一把这个行为描述成是引用捕获更方便一些。
  • 有些语言(例如Java)虽然目前只实现了值捕获,但是还要留着面子不承认自己只做了值捕获,所以只允许捕获不变量(final local),或者例如Java 8允许捕获事实上不变量(effectively final local)。这样,虽然实现用的是值捕获,但效果看起来跟引用捕获一样;就算以后的Java扩展到允许通用的(对可变变量的)引用捕获,也不会跟已有的代码发生不兼容。
public class Test {
    public static void main(String[] args)  {
         
    }
     
    public void test(final int b) {
        final int a = 10;
        new Thread(){
            public void run() {
                System.out.println(a);
                System.out.println(b);
            };
        }.start();
    }
}
  • 有些语言(例如Python)的lambda略奇葩,实现的是引用捕获,但是lambda内不能对捕获的变量赋值,只有原本定义那些变量的作用域里能对它们赋值。

相关文章

  • Kotlin原理-闭包

    讲kotlin的闭包我想从java的闭包讲起。 Java不完整闭包 Java的闭包是不完整的,它要求匿名内部类使用...

  • java,kotlin,dart闭包

    java闭包 kotlin闭包 dart闭包 了解不同语言之间的相同和不同。学习和进步。

  • JAVA闭包

    一、闭包的定义。 有很多不同的人都对闭包过进行了定义,这里收集了一些。 # 是引用了自由变量的函数。这个函数通常被...

  • java的闭包

    什么是闭包 1、一个含有自由变量的函数;2、这些自由变量所在的环境。也就是函数和环境的总和构成一个闭包。外部环境持...

  • 快速上手 Kotlin 开发系列之Lambda闭包

    本节讨论 Kotlin 的 Lambda 闭包、以及它的声明和原理 Lambda 闭包 我们先看一个 Java 中...

  • 闭包那点事,你知道白?

    定义:啥是闭包 本文将力求最全面,最普遍的总结对闭包的理解。 要想了解闭包,首先看一下变量作用域。 这就是Java...

  • Kotlin函数式编程 (3)✔️闭包与捕获变量

    闭包定义Java 与 Koltin 中 Lambda 捕获局部变量区别闭包捕获的变量可以脱离原始作用域而存在 一、...

  • Java中被阉割的闭包在Kotlin中的表现如何?

    1 闭包概述 闭包,Clousure。在Java中表现为Lambda表达式,在Koltin中表现为函数类型变量(或...

  • swift-闭包

    闭包 闭包定义 闭包简化 - 尾随闭包 闭包参数 闭包返回值 闭包的循环引用

  • 从面向对象角度看javascript的闭包

    本文翻译:梁开权 javascript的"闭包"是这样定义的: 闭包就是能够读取其他函数内部变量的函数。在java...

网友评论

      本文标题:java的闭包

      本文链接:https://www.haomeiwen.com/subject/pqpgqktx.html