[英]Preferring mutable or immutable collections as method parameters
我正在编写一个将在多个地方使用的库方法。 该方法的参数之一是对象的集合,并且该方法不会改变该集合。 方法签名应该指定一个可变的还是不可变的集合?
public static void foo(List<Bar> list) {
// ...
}
优点:客户端可以传入List<Bar>
或ImmutableList<Bar>
中的任何一个对他们来说更方便。
缺点: list
参数不会发生突变并不是很明显。 客户必须阅读文档和/或代码来实现这一点。 无论如何,客户可能会制作不必要的防御性副本。
public static void foo(ImmutableList<Bar> list) {
// ...
}
优点:客户可以保证list
参数不会发生变化。
缺点:如果客户端有List<Bar>
,他们必须在调用foo
之前先将其转换为ImmutableList<Bar>
。 这种转换浪费了少量时间,并且无论他们喜欢与否,它都是强加给客户的。
注意:出于这个问题的目的,我们假设所有客户端都可以使用 Guava 的ImmutableList
,例如因为库和客户端代码都属于已经在其他地方使用ImmutableList
的相同代码库。
作为foo()
API 的创建者,这不关你的事。 你拿一个清单,你不修改它,就是这样。 实际上,您的代码并不关心列表的可变性(这是调用者关心的问题):因此请记录您的意图并停在那里。
如果调用者需要保证列表不会被篡改,他们会创建防御性副本,这不是因为您没有 promise 保持列表不变,而是因为他们需要那个保证。
它遵循我们在方法实现中执行 null 检查的相同逻辑:需要它是因为我们的代码需要健壮,而不是因为调用者可以发送 null 参数。
换句话说,按照您打算实现它们的方式记录您的方法,并将其留给调用者来选择列表实现。 他们选择的原因会有所不同(即,并不总是只有您是否会修改列表)。
将其留在List
。
以下是一些需要考虑的情况:
Collections.synchronizedCollection
不会修改客户端的集合。
Collections.frequency
不会修改客户端的集合。
这些原因并不是 JDK 不公开不可变接口的原因。 这些原因在文档中进行了解释。 在synchronizedCollection
的情况下,虽然它不修改客户端的集合,但它确实返回了客户端集合的可修改视图; 有人会说这个 function 在这里不适用。 但是, frequency
和其他查询功能仍然很强大。
您不应该为了宣传安全而限制客户,仅此而已。 应该有更多的理由,否则您的帮助可能会成为客户的负担。 在某些情况下,您的目标可能与功能/系统正在实现的目标相矛盾,例如synchronizedCollection
示例。
鼓励安全是件好事,但是让您的系统将其强加给您的客户,而系统却没有从中受益,那就是滥用权力; 这不是你的决定。
ernest_k在他的回答中提出了一个非常好的观点,建议您需要分析您的系统应该负责什么,以及客户应该负责什么。 在这种情况下,集合是否不可变应该由客户端决定,因为您的系统不关心可变性。 正如他所说,“这不关你的事”,我同意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.