示例
此测试失败,因为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()”方法。从中返回的项目 结果迭代器将被传递给闭包。
通常情况下,我最终会花费大量时间尝试解决问题并使用谷歌搜索答案。难道不应该有更有效的方法吗?有吗?
答案 0 :(得分:5)
嗯,这与Java / Groovy编程基础不远。有对象,有变量。变量可以保存对象的“链接”,称为引用。所以基本上,使用变量可以访问存储在计算机内存深处的真实对象。
每当你改变变量(即赋予它某些东西)时,你永远不会修改真实对象。相反,变量开始指向一些不同的对象。
现在,再次查看文档:
迭代聚合类型或数据结构,传递每个 项目到给定的闭包。
就是这样。它为您提供了指向每个项目的变量。如果覆盖已经给出的局部变量,变量将开始指向其他对象,就是这样。该列表仍然具有对旧对象的引用。
该信息是使用Java和类似语言编程所需的最基本的知识。通常在手册/文档的第一页解释。因为它是基本的,没有人会为你有某种参数的每个函数反复解释它。
答案 1 :(得分:1)
@Max上面提供了一个很好的答案。我花2美分。变量或引用实际上是java中的按值传递。理解这一点也很重要。请注意,对象本身不会被复制,只会复制对它的引用。
现在让我们回到列表中。它引用了其中的所有对象。当您在列表中调用each
时,会创建一个指向相同对象的新引用,并将其传递给each
方法。因此,即使您将此新创建的引用变量指向另一个对象,列表中的引用仍然保持不变并指向同一个旧对象。