ImmutableList vs List-我应该把它作为什么?

时间:2015-04-15 15:22:26

标签: java collections guava

我知道通常会接受将所有List实施内容强制转换为List。无论是变量,方法返回,还是使用ArrayListCopyOnWriteArrayList等的方法参数

List<Market> mkts = new ArrayList<>();

当我使用Guava ImmutableList时,我觉得它可以说是这个规则的一个例外(特别是如果我正在构建内部复杂的业务应用程序而不是公共API)。因为如果我将其转换为列表,则不推荐使用已弃用的mutator方法将其标记为已弃用。此外,它不再被识别为不可变对象,这是其功能和身份的一个非常重要的部分。

List<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);

因此将它作为ImmutableList权利传递是有意义的吗?我甚至认为内部API的良好策略只接受ImmutableList,因此客户端的可变性和多线程不会破坏libary中的任何内容。

ImmutableList<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);

我知道ImmutableList本身有被弃用的风险,而Oracle决定创建自己的ImmutableList的那天将需要大量的重构。但是,维持ImmutableList演员的优点可以超过缺点吗?

5 个答案:

答案 0 :(得分:6)

我同意你的理由。如果您正在使用Guava集合库并且您的列表是不可变的,那么将它们作为ImmutableList传递是个好主意。

然而:

  

我知道ImmutableList本身有被弃用的风险,而Oracle决定创建自己的ImmutableList的那一天将需要大量的重构。

第一种情况似乎不太可能,但只要您使用任何第三方库,就会冒这个风险。但另一方面,如果他们(Google)无偿地弃用您所依赖的类或方法,您可以选择不升级您的应用程序的Guava版本。

<强>更新

Louis Wasserman(曾为谷歌工作)在评论中说:

  

“Guava为非@ Beta API提供了非常强大的兼容性保证。”

因此,我们可以忽略无偿API更改的可能性。


第二种情况更不可能(IMO)。而且你可以肯定,如果Oracle确实添加了一个不可变的列表类或接口,那就不会要求你重构。 Oracle在增强标准API时非常难以避免破坏现有代码。

但话说回来,你应该权衡利弊......以及如果最终会如何应对利弊。

答案 1 :(得分:1)

不幸的是,Java中没有相应的接口(很可能永远不会)。所以我的想法是假装ImmutableList是一个界面。 :D但严重的是,它增加了不应该丢失的重要信息。

古老的规则一切都来自实际状态,例如&#34;针对接口的程序&#34;。 IIRC在规则创建时,没有Java和&#34;接口&#34;表示编程接口,即合同,而不是java interface

这样的方法
void strange(ArrayList list) {...}

显然很奇怪,因为没有理由不使用List。包含ImmutableList的签名有充分的理由。


  

我知道ImmutableList本身有被弃用的风险,而Oracle决定创建自己的ImmutableList的那一天将需要大量的重构。

你的意思是Java 18?让我们看看,但是Guava的ImmutableList非常好,并且在设计这样一个类别时没有多大意义。因此,您可以希望大多数更改仅在您的导入中。到2050年,问题会比这更糟。

答案 2 :(得分:1)

继续使用List而不是ImmutableList由于以下几个原因,您的API无需明确开始使用ImmutableLists,因此没有任何问题:

  1. ImmutableList只是Guava,不太可能在任何时候成为标准Java。不要将你的代码和编码习惯绑定到第三方库(即使它像Guava一样很酷)。
  2. 在Java中使用不可变对象是一种很好的做法,在开发API时尤其重要(参见Effective Java Item 15 - 最小化可变性)。这是一个普遍的概念,可以理所当然,不需要以接口的名义传达。同样,您不会考虑调用专为继承UserThatCanBeSubclassed设计的User类。
  3. 在稳定性的名称中,您的API永远不应该开始修改传递给它的List,并且在将List传递给客户端时始终制作防御性副本。在此处引入ImmutableList会诱使您和您的API的客户产生虚假的安全感,并诱使他们违反该规则。

答案 3 :(得分:0)

我理解你的困境。

Personnaly,我建议继续使用List作为引用类型(为了面向未来并从多态中受益),并使用@Immutable注释来传达它是不可变的信息。

注释比普通的javadoc注释更明显,你甚至可以使用JSR-305(ex-JCIP)中的注释。 一些静态分析工具甚至可以检测它并验证您的对象是否未发生变异。

答案 4 :(得分:0)

我宁愿只使用List方法参数。强制调用者传递ImmutableList没有多大好处 - 这是你自己的方法,你也不会改变列表,但是你有更多可重用和通用的方法。

作为一种返回类型,我会使用ImmutableList让方法用户知道此列表无法修改。

相关问题