ImmutableList vs List-我应该将其转换为什么?
ImmutableList vs List- what should I cast it as?
我知道将所有 List
实施转换为 List
是普遍接受的做法。无论是变量、方法return,还是使用ArrayList
、CopyOnWriteArrayList
等的方法参数
List<Market> mkts = new ArrayList<>();
当我使用 Guava ImmutableList
时,我感觉它可以说是这条规则的一个例外(特别是如果我正在构建内部复杂的业务应用程序而不是 public API)。因为如果我把它放到列表中,已弃用的增变器方法将不再被标记为已弃用。此外,它不再被标识为不可变对象,这是其功能和身份的一个非常重要的部分。
List<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);
因此将它作为 ImmutableList
传递是有意义的,对吗?我什至可以争辩说,内部 API 只接受 ImmutableList
是一个很好的策略,因此客户端的可变性和多线程不会破坏库中的任何东西。
ImmutableList<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);
我知道 ImmutableList
本身存在被弃用的风险,Oracle 决定创建自己的 ImmutableList
的那一天将需要大量重构。但是否可以说维持 ImmutableList
演员阵容的利大于弊?
不幸的是,Java 中没有相应的界面(很可能永远不会)。所以我的做法是假装 ImmutableList
是一个接口。 :D 但说真的,它添加了不应丢失的重要信息。
这一切都来自古老的规则,实际上是这样说的 "program against interfaces"。 IIRC 在创建规则时,周围没有 Java,"interface" 表示编程接口,即合同,而不是 java interface
。
类似
的方法
void strange(ArrayList list) {...}
显然很奇怪,因为没有理由不使用 List
。包含 ImmutableList
的签名有充分的理由。
I know there is a risk of ImmutableList itself becoming deprecated, and the day Oracle decides to create its own ImmutableList will require a lot of refactoring.
你是说Java 18?让我们看看,但是 Guava 的 ImmutableList
非常好,设计这样一个 class 不同的意义不大。因此,您可以希望大多数更改仅发生在您的导入中。到 2050 年,还会有比这更严重的问题。
我理解你的困境。
Personnaly,我会建议继续使用 List
作为引用类型(面向未来并从多态性中受益),并使用 @Immutable
注释来传达它是不可变的。
注释比普通的 javadoc 注释更明显,您甚至可以使用 JSR-305(ex-JCIP)中的注释。
一些静态分析工具甚至可以检测到它并验证您的对象没有发生变异。
我宁愿只使用 List
作为方法参数。强制调用者传递 ImmutableList
没有多大好处 - 这是你自己的方法,无论如何你都不会改变列表,但你会有更可重用和通用的方法。
作为 return 类型,我会选择 ImmutableList
让方法用户知道无法修改此列表。
我同意你的理由。如果您使用的是 Guava 集合库并且您的列表是不可变的,那么将它们作为 ImmutableList
传递是个好主意。
但是:
I know there is a risk of ImmutableList itself becoming deprecated, and the day Oracle decides to create its own ImmutableList will require a lot of refactoring.
第一种情况似乎不太可能,但无论何时使用 any 第 3 方库,这都是一种风险。但不利的一面是,如果应用程序的 Guava 版本 (Google) 无故弃用了您所依赖的 class 或方法,您可以选择不升级它们。
更新
Louis Wasserman(为 Google 工作)在评论中说:
"Guava provides pretty strong compatibility guarantees for non-@Beta APIs."
因此我们可以降低无故 API 更改的可能性。
第二种情况更不可能(IMO)。而且您可以确定,如果 Oracle 确实添加了不可变列表 class 或接口,那将不会 要求 您进行重构。 Oracle 在增强标准 APIs.
时非常努力地避免破坏现有代码
但话虽如此,权衡利弊……以及如果最终发生时您将如何处理利弊,真的取决于您。
继续使用 List
而不是 ImmutableList
! 这没有问题,您的 API 也没有理由开始使用 ImmutableLists
明确地出于几个原因:
ImmutableList
只是 Guava,在任何时候都不太可能成为标准 Java。不要将您的代码和编码习惯绑定到第三方库(即使它是像 Guava 这样很酷的库)。
- 在 Java 中使用不可变对象是一种很好的做法,并且在开发 API 时尤为重要(请参阅有效 Java 项目 15 - 最小化可变性)。这是一个可以想当然的通用概念,不需要以接口的名称来传达。同样,您也不会考虑调用为继承
UserThatCanBeSubclassed
而设计的用户 class。
- 以稳定性的名义,您的 API 永远不应开始修改传递给它的
List
,并且在将 List
传递给客户端时始终制作防御性副本。在这里介绍 ImmutableList
会引诱您和您 API 的客户产生一种虚假的安全感,并诱使他们违反该规则。
我知道将所有 List
实施转换为 List
是普遍接受的做法。无论是变量、方法return,还是使用ArrayList
、CopyOnWriteArrayList
等的方法参数
List<Market> mkts = new ArrayList<>();
当我使用 Guava ImmutableList
时,我感觉它可以说是这条规则的一个例外(特别是如果我正在构建内部复杂的业务应用程序而不是 public API)。因为如果我把它放到列表中,已弃用的增变器方法将不再被标记为已弃用。此外,它不再被标识为不可变对象,这是其功能和身份的一个非常重要的部分。
List<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);
因此将它作为 ImmutableList
传递是有意义的,对吗?我什至可以争辩说,内部 API 只接受 ImmutableList
是一个很好的策略,因此客户端的可变性和多线程不会破坏库中的任何东西。
ImmutableList<Market> mkts = ImmutableList.of(mkt1,mkt2,mkt3);
我知道 ImmutableList
本身存在被弃用的风险,Oracle 决定创建自己的 ImmutableList
的那一天将需要大量重构。但是否可以说维持 ImmutableList
演员阵容的利大于弊?
不幸的是,Java 中没有相应的界面(很可能永远不会)。所以我的做法是假装 ImmutableList
是一个接口。 :D 但说真的,它添加了不应丢失的重要信息。
这一切都来自古老的规则,实际上是这样说的 "program against interfaces"。 IIRC 在创建规则时,周围没有 Java,"interface" 表示编程接口,即合同,而不是 java interface
。
类似
的方法void strange(ArrayList list) {...}
显然很奇怪,因为没有理由不使用 List
。包含 ImmutableList
的签名有充分的理由。
I know there is a risk of ImmutableList itself becoming deprecated, and the day Oracle decides to create its own ImmutableList will require a lot of refactoring.
你是说Java 18?让我们看看,但是 Guava 的 ImmutableList
非常好,设计这样一个 class 不同的意义不大。因此,您可以希望大多数更改仅发生在您的导入中。到 2050 年,还会有比这更严重的问题。
我理解你的困境。
Personnaly,我会建议继续使用 List
作为引用类型(面向未来并从多态性中受益),并使用 @Immutable
注释来传达它是不可变的。
注释比普通的 javadoc 注释更明显,您甚至可以使用 JSR-305(ex-JCIP)中的注释。 一些静态分析工具甚至可以检测到它并验证您的对象没有发生变异。
我宁愿只使用 List
作为方法参数。强制调用者传递 ImmutableList
没有多大好处 - 这是你自己的方法,无论如何你都不会改变列表,但你会有更可重用和通用的方法。
作为 return 类型,我会选择 ImmutableList
让方法用户知道无法修改此列表。
我同意你的理由。如果您使用的是 Guava 集合库并且您的列表是不可变的,那么将它们作为 ImmutableList
传递是个好主意。
但是:
I know there is a risk of ImmutableList itself becoming deprecated, and the day Oracle decides to create its own ImmutableList will require a lot of refactoring.
第一种情况似乎不太可能,但无论何时使用 any 第 3 方库,这都是一种风险。但不利的一面是,如果应用程序的 Guava 版本 (Google) 无故弃用了您所依赖的 class 或方法,您可以选择不升级它们。
更新
Louis Wasserman(为 Google 工作)在评论中说:
"Guava provides pretty strong compatibility guarantees for non-@Beta APIs."
因此我们可以降低无故 API 更改的可能性。
第二种情况更不可能(IMO)。而且您可以确定,如果 Oracle 确实添加了不可变列表 class 或接口,那将不会 要求 您进行重构。 Oracle 在增强标准 APIs.
时非常努力地避免破坏现有代码但话虽如此,权衡利弊……以及如果最终发生时您将如何处理利弊,真的取决于您。
继续使用 List
而不是 ImmutableList
! 这没有问题,您的 API 也没有理由开始使用 ImmutableLists
明确地出于几个原因:
ImmutableList
只是 Guava,在任何时候都不太可能成为标准 Java。不要将您的代码和编码习惯绑定到第三方库(即使它是像 Guava 这样很酷的库)。- 在 Java 中使用不可变对象是一种很好的做法,并且在开发 API 时尤为重要(请参阅有效 Java 项目 15 - 最小化可变性)。这是一个可以想当然的通用概念,不需要以接口的名称来传达。同样,您也不会考虑调用为继承
UserThatCanBeSubclassed
而设计的用户 class。 - 以稳定性的名义,您的 API 永远不应开始修改传递给它的
List
,并且在将List
传递给客户端时始终制作防御性副本。在这里介绍ImmutableList
会引诱您和您 API 的客户产生一种虚假的安全感,并诱使他们违反该规则。