首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是闭包?java有闭包吗?

什么是闭包?java有闭包吗?
EN

Stack Overflow用户
提问于 2010-09-27 23:48:36
回答 5查看 21.7K关注 0票数 29

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-09-27 23:58:26

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

大体来说,这意味着:

  • 您可以将闭包作为参数传递给其他函数
  • 闭包存储在创建

时存在的词法作用域中的一些变量的值

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

代码语言:javascript
复制
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);
    }
}
票数 29
EN

Stack Overflow用户

发布于 2010-09-27 23:56:10

在不同的语言中,闭包有不同的名称,但要点如下:

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

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

代码语言:javascript
复制
foo("bar", "baz" function(x){alert("x")});

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

闭包“关闭”变量,因此可以用来传递限定了作用域的变量。考虑这个例子:

代码语言:javascript
复制
function foo(){
    var spam = " and eggs";
    return function(food){alert(food + spam)};
}
var sideOfEggs = foo();

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

所以我们清楚了闭包可以访问其父对象的私有作用域变量,对吧?那么如何在javascript中使用它们来模拟私有访问修饰符呢?

代码语言: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还没有闭包。它最接近的是匿名内部类。然而,为了实例化其中的一个内联,你必须实例化一个完整的对象(通常来自现有的接口).The闭包的美妙之处在于它们封装了简单的、富有表现力的语句,而这些语句多少被匿名内部类的嘈杂所掩盖。

票数 14
EN

Stack Overflow用户

发布于 2011-04-08 04:33:05

虽然Java没有一流的函数,但它实际上有词法闭包。

例如,下面的Lisp函数(从Paul Graham关于Lisp的书中窃取)返回一个加一个数字的函数:

代码语言:javascript
复制
(defun make-adder (n)
  (lambda (x) (+ x n))

这可以在Java中完成。但是,由于它没有一流的函数,我们需要定义一个接口(让我们称它为Adder)和一个匿名内部类,以及一个实现该接口的函数。

代码语言:javascript
复制
public interface Adder {
    int add(int x);
}

public static Adder makeAdder(final int n) {
    return new Adder() {
        public int add(int x) {
            return x + n;
        }
    };
}

内部add()函数是一个词法闭包,因为它使用外部词法作用域中的n变量。

为此,必须将该变量声明为final,这意味着该变量不能更改。但是,更改引用变量中的值是可能的,即使它们是最终的。例如,考虑下面的Lisp函数(也来自于Lisp):

代码语言:javascript
复制
(defun make-adderb (n)
  (lambda (x &optional change)
    (if change
        (setq n x)
        (+ n n))))

这可以在Java中通过将外部变量包装在引用类型变量中来实现,比如数组或对象。

代码语言:javascript
复制
public interface MutableAdder {
    int add(int x, boolean change);
}

public static MutableAdder makeAdderB(int n) {
    final int[] intHolder = new int[] { n };
    return new MutableAdder() {
        public int add(int x, boolean change) {
            if (change) {
                intHolder[0] = x;
                return x;
            }
            else {
                return intHolder[0] + x;
            }
        }
    };
}

我会说这是真正的词法闭包,而不是模拟。但我不会说它很漂亮。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3805474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档