3 回答
TA贡献1942条经验 获得超3个赞
由于您的示例使用私有字段,因此隐藏实现类型并不重要。您(或维护此类的任何人)始终可以查看字段的初始值设定项以查看它是什么。
但是,根据它的使用方式,可能值得为该字段声明一个更具体的接口。将其声明为 a 表示允许重复,并且排序很重要。将其声明为 a 表示不允许重复,并且排序并不重要。您甚至可以将字段声明为具有特定的实现类(如果其中有重要内容)。例如,将其声明为 “表示不允许重复项,但排序很重要。List
Set
LinkedHashSet
如果类型出现在类的公共 API 中,以及该类的兼容性约束是什么,那么是否使用接口以及使用哪个接口的选择将变得更加重要。例如,假设有一个方法
public ??? getRegisteredListeners() { return ... }
现在,返回类型的选择会影响其他类。如果您可以更改所有呼叫者,也许这没什么大不了的,您只需要编辑其他文件即可。但假设调用方是一个您无法控制的应用程序。现在,接口的选择至关重要,因为您无法在不破坏应用程序的情况下更改它。这里的规则通常是选择最抽象的接口,以支持您希望调用方想要执行的操作。
大多数 Java SE API 返回 。这提供了从底层实现的相当程度的抽象,但它也为调用方提供了一组合理的操作。调用方可以迭代、获取大小、执行包含检查或将所有元素复制到另一个集合。Collection
某些代码库用作要返回的最抽象的接口。它所做的只是允许调用方进行迭代。有时这是所有必要的,但与 相比,它可能有些限制。Iterable
Collection
另一种选择是返回 .如果您认为调用方可能希望使用流的操作(如筛选、映射、查找等),而不是迭代或使用集合操作,这将非常有用。Stream
请注意,如果选择返回 或 ,则需要确保返回不可修改的视图或创建防御性副本。否则,调用方可能会修改类的内部数据,这可能会导致 bug。(是的,即使是可以修改!请考虑获取 一个,然后调用该方法。如果返回 ,则无需担心,因为不能使用 来修改基础源。Collection
Iterable
Iterable
Iterator
remove()
Stream
Stream
请注意,我将有关字段声明的问题转换为有关方法返回类型声明的问题。有一种“编程到接口”的想法在Java中非常普遍。在我看来,对于局部变量来说,这并不重要(这就是为什么它通常可以使用),对于私有字段来说也无关紧要,因为这些(几乎)根据定义只影响它们被声明的类。但是,“程序到接口”原则对于API签名非常重要,因此在这些情况下,您确实需要考虑接口类型。私人领域,不是那么多。var
(最后一点:有一种情况是,你需要关注私有字段的类型,那就是当你使用一个直接操作私有字段的反射框架时。在这种情况下,您需要将这些字段视为公共字段 - 就像方法返回类型一样 - 即使它们未声明。public
TA贡献1817条经验 获得超6个赞
与所有事情一样,这是一个权衡问题。有两种对立的力量。
类型越通用,实现的自由度就越高。如果您使用,则可以自由使用 、或,而不会影响用户/调用方。
Collection
ArrayList
HashSet
LinkedList
返回类型越通用,用户/调用方可用的功能就越少。提供基于索引的查找。A 使得通过 、 和 获取连续子集变得容易。A 提供了高效的 O(log n) 二进制搜索查找方法。如果您返回 ,则这些都不可用。只能使用最通用的访问函数。
List
SortedSet
headSet
tailSet
subSet
NavigableSet
Collection
此外,子类型保证特殊属性不:s 保存唯一项。已排序。有订单;它们不是无序的物品袋。如果使用,则用户/调用方不一定假定这些属性成立。他们可能被迫进行防御性编码,例如,即使您知道不会有重复项,也可以处理重复项。Collection
Set
SortedSet
List
Collection
合理的决策过程可能是:
如果 O(1) 索引访问得到保证,请使用 。
List
如果元素已排序且唯一,请使用 或 。
SortedSet
NavigableSet
如果元素唯一性得到保证,但顺序没有保证,请使用 。
Set
否则,请使用 。
Collection
TA贡献1784条经验 获得超7个赞
这实际上取决于您要对集合对象执行的操作。
Collection<String> cSet = new HashSet<>(); Collection<String> cList = new ArrayList<>();
在这种情况下,如果你愿意,你可以做:
cSet = cList;
但如果你喜欢:
Set<String> cSet = new HashSet<>();
尽管您可以使用构造函数构造新列表,但不允许执行上述操作。
Set<String> set = new HashSet<>(); List<String> list = new ArrayList<>(); list = new ArrayList<>(set);
所以基本上取决于你可以使用的用法或接口。Collection
Set
添加回答
举报