请查看groovy中的以下代码段:
def static void main(String... args) { def arr = [1, 2, 3, 4, 5] for (int f in arr) { Thread.start { print f + ', '} } } Out: 2, 3, 5, 5, 5,
我对此输出感到惊讶.为什么"5"被多次打印?而且,在Java中运行等效代码的一切看起来都很好:
public static void main(String[] args) { int[] arr = new int[]{1, 2, 3, 4, 5}; for (int f : arr) { new Thread(() -> { System.out.print(f + ", "); }).start(); } } Out: 1, 5, 4, 3, 2,
任何人都可以解释为什么会这样吗?看起来groovy的问题在Closure实现中.但是,这种行为很奇怪.它是某种bug还是我没有意识到groovy是如何工作的?
谢谢!
Java闭包在创建时关闭不可变值f
,而Groovy闭包关闭可变变量 f
.
因此,一旦Groovy循环完成,f
包含5
和之后正在运行的线程将打印5
.
Java闭包可以关闭一个最终或"有效最终"的变量引用,这意味着它除了名称之外都是最终的.请参阅Java 8:Lambdas,第1部分.这就是内部类可以做的事情以及一些有用的便利.
Groovy闭包是非常不同的对象,它们早于Java闭包.请参阅Groovy Closures,其中示例{ ++item }
修改封闭范围中的变量.
Groovy将闭包定义为Closure类的实例.它使它与Java 8中的lambda表达式截然不同.委托是Groovy闭包中的一个关键概念,它在lambda中没有等价物.能够更改委托或更改闭包的委派策略使得在Groovy中设计漂亮的域特定语言(DSL)成为可能.
底线 Groovy旨在成为与Java具有最佳"阻抗匹配"的动态语言,但是现在Java已经有了lambdas,这两种语言仍然存在分歧.警告程序员.