我怎么知道Groovy的each()不会改变列表的元素?

时间:2013-05-08 10:25:59

标签: groovy

示例

此测试失败,因为each不会修改列表的元素。

void test_each_DoesNotModifyListElements() {
    List<String> list = ["a", "b", "c"]
    list.each { it =  it + "z" }
    assert ["az", "bz", "cz"] == list
}

此测试通过,因为collect返回包含已修改元素的新列表。

void test_collect_ReturnsNewListWithModifiedElements() {
    List<String> list = ["a", "b", "c"]
    list = list.collect{ it + "z" }
    assert ["az", "bz", "cz"] == list
}

假设

此时,我假设each没有修改列表的元素,因为我已经编写了下面的测试,我假设这是测试告诉我的。如果我错了,请纠正我。

void test_each_DoesNotModifyListElements1() {
    List<String> list = ["a", "b", "c"]
    list.each { it + "z" }
    assert ["az", "bz", "cz"] == list
}

void test_each_DoesNotModifyListElements2() {
    List<String> list = ["a", "b", "c"]
    list.each { it =  it + "z" }
    assert ["az", "bz", "cz"] == list
}

void test_each_DoesNotModifyListElements3() {
    List<String> list = ["a", "b", "c"]
    list = list.each { it =  it + "z" }
    assert ["az", "bz", "cz"] == list
}

问题

所以问题是:作为一个Groovy初学者,我应该如何预先知道,在编写测试和googling之前的意思,each不会改变列表的元素?

阅读文档?

  

Groovy each documentation:迭代聚合类型或数据结构,传递每个   项目到给定的闭包。自定义类型可以使用此方法   只需提供一个“iterator()”方法。从中返回的项目   结果迭代器将被传递给闭包。

通常情况下,我最终会花费大量时间尝试解决问题并使用谷歌搜索答案。难道不应该有更有效的方法吗?有吗?

2 个答案:

答案 0 :(得分:5)

嗯,这与Java / Groovy编程基础不远。有对象,有变量。变量可以保存对象的“链接”,称为引用。所以基本上,使用变量可以访问存储在计算机内存深处的真实对象。

每当你改变变量(即赋予它某些东西)时,你永远不会修改真实对象。相反,变量开始指向一些不同的对象。

现在,再次查看文档:

  

迭代聚合类型或数据结构,传递每个   项目到给定的闭包。

就是这样。它为您提供了指向每个项目的变量。如果覆盖已经给出的局部变量,变量将开始指向其他对象,就是这样。该列表仍然具有对旧对象的引用。

该信息是使用Java和类似语言编程所需的最基本的知识。通常在手册/文档的第一页解释。因为它是基本的,没有人会为你有某种参数的每个函数反复解释它。

答案 1 :(得分:1)

@Max上面提供了一个很好的答案。我花2美分。变量或引用实际上是java中的按值传递。理解这一点也很重要。请注意,对象本身不会被复制,只会复制对它的引用。

现在让我们回到列表中。它引用了其中的所有对象。当您在列表中调用each时,会创建一个指向相同对象的引用,并将其传递给each方法。因此,即使您将此新创建的引用变量指向另一个对象,列表中的引用仍然保持不变并指向同一个旧对象。