Groovy - Closures和bind,为什么这段代码不起作用?

时间:2010-09-10 15:42:38

标签: groovy closures

我认为这是一个新手问题,但为什么它在最后一个断言中失败了? 我认为闭包绑定了它的值,所以从闭包中改变它会改变闭包之外的值。

def value = 5

def foo(n){

  return {

    ++n

  }
}

def test = foo(value)

assert test() == 6
assert test() == 7

assert value == 7

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

这似乎是一种奇怪的行为,但我认为这是正确的。所有对象事件整数都通过引用传递。调用foo(value)将值传递给函数。变量'n'是与'value'引用相同的对象的引用。基本上你有两个指向同一个对象的指针。当你递增'n'时,你只是递增那个变量。

由于Integer类是不可变的,因此++ n实际上是这样的:

n = n + 1

这是将递增的值赋给变量n。在顶部声明的变量'value'仍然指向原始对象5.

答案 1 :(得分:1)

请记住,Integer(value的运行时类型)是不可变的。因此,尽管nvalue最初引用同一个对象,但当您执行++n时,它会创建一个新的Integervalue引用未更新以引用此新对象,因此在执行完成时它仍然引用初始对象(5)。

答案 2 :(得分:0)

您要为名称n分配一个新值,该值与名称value不同。您可以通过使value成为可变对象来获得所需的行为。然后,您可以更改它,而不是创建和分配新对象。

这是一个将值包装在列表中的简单示例:

def value = [5]

def foo(n){

    return {

        n[0]++
        n
    }
}

def test = foo(value)

assert test() == [6]
assert test() == [7]

assert value == [7]