groovy是否尊重闭包或匿名类外部定义的最终变量?

groovy是否尊重闭包或匿名类外部定义的最终变量?,groovy,scope,closures,final,Groovy,Scope,Closures,Final,今天,我在将一些java代码移植到groovy时发现了groovy的一些核心行为 我们在java中一直在做的事情:在循环中构建匿名类(例如用于操作)并引用在该类之外声明的最终变量 如果让您在groovy中运行此代码,您将意外地得到的不是1,2,3,4,5,6,7,8,9,而是9,9,9,9,9,9,9。这意味着groovy不会将各自的最终变量i绑定到每个匿名类,而是在执行时使用最后一个设置值 我在groovy文档中找不到这种行为的任何原因。顺便说一下,如果我使用groovy闭包而不是匿名类,我会

今天,我在将一些java代码移植到groovy时发现了groovy的一些核心行为

我们在java中一直在做的事情:在循环中构建匿名类(例如用于操作)并引用在该类之外声明的最终变量

如果让您在groovy中运行此代码,您将意外地得到的不是1,2,3,4,5,6,7,8,9,而是9,9,9,9,9,9,9。这意味着groovy不会将各自的最终变量i绑定到每个匿名类,而是在执行时使用最后一个设置值

我在groovy文档中找不到这种行为的任何原因。顺便说一下,如果我使用groovy闭包而不是匿名类,我会得到同样的行为

public static void main(String[] args) {
    int[] list = new int[10];
    for (int i = 0; i < 10; i++) {
        list[i] = i;
    }
    Runnable[] runnables = new Runnable[10];
    for (final int i : list) {
        runnables[i] = new Runnable() {
            @Override
            public void run() {
                System.out.println(i);
            }
        };
    }

    for (int i = 0; i < 10; i++) {
        runnables[i].run();
    }
}
publicstaticvoidmain(字符串[]args){
int[]列表=新int[10];
对于(int i=0;i<10;i++){
列表[i]=i;
}
Runnable[]runnables=新的Runnable[10];
用于(最终int i:列表){
runnables[i]=新的Runnable(){
@凌驾
公开募捐{
系统输出打印LN(i);
}
};
}
对于(int i=0;i<10;i++){
runnables[i].run();
}
}

奇数。。。我会调查这是否是已知的行为

同时,您可以通过在生成Runnable的循环中声明另一个变量来解决此问题,然后在Runnable中使用此变量:

for (int i : list) {
    int k = i
    runnables[i] = new Runnable() {
        @Override
        public void run() {
            System.out.println(k);
        }
    }
}
或者使用
collect
生成可运行数组:

Runnable[] runnables = list.collect { i -> 
    new Runnable() {
        @Override
        public void run() {
            System.out.println( i );
        }
    }
}
编辑
我四处询问过,在类属性之外,
final
目前被Groovy忽略。这是将来可以添加的内容,不过我相信问题在于
for
循环。简化代码:

def runnables = []
for (int i: 0..9) {
    runnables << {
        println i
    }
}
runnables*.call() // prints 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
使用范围代替
for
循环将按预期工作:

def runnables = []
(0..9).each { i ->
    runnables << {
        println i
    }
}
runnables*.call() // prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
def runnables=[]
(0..9)。每个{i->
可运行
def runnables = []
(0..9).each { i ->
    runnables << {
        println i
    }
}
runnables*.call() // prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9