什么是闭包?Java有闭包吗?

2022-09-01 05:53:44

我正在阅读面向对象的Javascript,并发现了闭包的概念。我不太明白为什么以及何时使用它。其他语言(如Java)也有闭包吗?我基本上想了解了解闭包的概念如何帮助我改进编码。


答案 1

闭包是具有绑定变量的第一类函数。

大致这意味着:

  • 您可以将闭包作为参数传递给其他函数
  • 闭包存储创建时存在的词法作用域中的某些变量的值

Java最初没有对闭包的语法支持(这些是在Java 8中引入的),尽管使用匿名内部类模拟它们是相当普遍的做法。下面是一个示例:

import java.util.Arrays;
import java.util.Comparator;

public class StupidComparator { 
    public static void main(String[] args) {
        // this is a value used (bound) by the inner class
        // note that it needs to be "final"
        final int numberToCompareTo=10;

        // this is an inner class that acts like a closure and uses one bound value
        Comparator<Integer> comp=new Comparator<Integer>() {
            public int compare(Integer a, Integer b) {
                int result=0;
                if (a<numberToCompareTo) result=result-1;
                if (b<numberToCompareTo) result=result+1;
                return result;
            }
        };

        Integer[] array=new Integer[] {1,10, 5 , 15, 6 , 20, 21, 3, 7};

        // this is a function call that takes the inner class "closure" as a parameter
        Arrays.sort(array,comp);

        for (int i:array) System.out.println(i);
    }
}

答案 2

闭包在各种语言中都有各种名称,但要点如下:

要创建闭包,您需要一种语言,其中函数类型是一等公民,即它可以绑定到变量并像任何旧字符串,int或bool一样传递。

您还需要能够以内联方式声明函数。在javascript中,你可以做这样的事情:

foo("bar", "baz" function(x){alert("x")});

将匿名函数作为参数传递给 foo 函数。我们可以用它来创建一个闭包。

闭包“关闭”变量,因此可用于传递作用域变量。请考虑以下示例:

function foo(){
    var spam = " and eggs";
    return function(food){alert(food + spam)};
}
var sideOfEggs = foo();

鸡蛋的一侧现在包含一个函数,它将“和鸡蛋”附加到它传递的任何食物上。spam 变量是 foo 函数作用域的一部分,在函数退出时会丢失,只是闭包“关闭”了命名空间,只要闭包保留在内存中,它就会保留它。

因此,我们很清楚闭包可以访问其父级的私有范围变量,对吗?那么如何使用它们在javascript中模拟私有访问修饰符呢?

var module = (function() {   
    var constant = "I can not be changed";

     return {
         getConstant    :    function() {  //This is the closure
            return constant;               //We're exposing an otherwise hidden variable here
         }
    };
}());                                     //note the function is being defined then called straight away

module.getConstant();                     //returns "I can not be changed"
module.constant = "I change you!";
module.getConstant();                     //still returns "I can not be changed" 

所以这里发生的事情是我们正在创建并立即调用一个匿名函数。函数中有一个私有变量。它返回一个对象,其中包含引用此变量的单个方法。函数退出后,getConstant 方法是访问变量的唯一方法。即使删除或替换此方法,也不会放弃它的秘密。我们已经使用闭包来实现封装和变量隐藏。有关此内容的更全面说明,请参阅 http://javascript.crockford.com/private.html

Java还没有闭包(它最接近的是匿名内部类。但是,要实例化其中一个内联对象,您必须实例化整个对象(通常来自现有接口)。闭包的美妙之处在于它们封装了简单,富有表现力的陈述,这些陈述在匿名内部类的噪音中有些迷失了。