我知道通常会接受将所有List
实施内容强制转换为List
。无论是变量,方法返回,还是使用ArrayList
,CopyOnWriteArrayList
等的方法参数
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
演员的优点可以超过缺点吗?
答案 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
,因此没有任何问题:
ImmutableList
只是Guava,不太可能在任何时候成为标准Java。不要将你的代码和编码习惯绑定到第三方库(即使它像Guava一样很酷)。UserThatCanBeSubclassed
设计的User类。 List
,并且在将List
传递给客户端时始终制作防御性副本。在此处引入ImmutableList
会诱使您和您的API的客户产生虚假的安全感,并诱使他们违反该规则。答案 3 :(得分:0)
我理解你的困境。
Personnaly,我建议继续使用List
作为引用类型(为了面向未来并从多态中受益),并使用@Immutable
注释来传达它是不可变的信息。
注释比普通的javadoc注释更明显,你甚至可以使用JSR-305(ex-JCIP)中的注释。 一些静态分析工具甚至可以检测它并验证您的对象是否未发生变异。
答案 4 :(得分:0)
我宁愿只使用List
方法参数。强制调用者传递ImmutableList
没有多大好处 - 这是你自己的方法,你也不会改变列表,但是你有更多可重用和通用的方法。
作为一种返回类型,我会使用ImmutableList
让方法用户知道此列表无法修改。