2010-05-26 34 views
31

我有一个对象,它将一些数据存储在列表中。实现可能会稍后改变,我不想将内部实现公开给最终用户。但是,用户必须有能力修改和访问这个数据集合。目前我有这样的事情:使用列表或集合更好吗?

public List<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(List<SomeDataType> data) { 
    this.data = data; 
} 

这是否意味着我已允许内部实现细节泄漏?我应该这样做吗?

public Collection<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(Collection<SomeDataType> data) { 
    this.data = new ArrayList<SomeDataType>(data); 
} 
+9

有一点需要记住的是,如果你像这样返回实际的集合或列表,你允许别人做他们想做的任何事情,包括删除项目甚至清除整个事情。您最好返回一个不可变的包装或列表副本。 – 2010-05-26 23:55:57

+1

@PaulTomblin是真实的,但它对系统有点矫枉过正和人为的开销。不可修改的包装器在处理由持久性中间件管理的对象时是有意义的,甚至在极少数情况下也是如此。 – comeGetSome 2013-05-10 22:06:03

+0

@comeGetSome,这就是为什么我说“可能”而不是“必须”。这取决于用例 - 如果我为他人使用API​​,我会返回一个副本或包装。如果是为了我自己或是为了值得信任的同事,我会在javadoc中放入一个大的“不要修改这个价值”,然后放在那里。 – 2013-05-11 15:21:44

回答

24

它只是取决于,你想让你的用户能够索引到数据?如果是,请使用列表。两者都是接口,所以你不会泄漏实现细节,实际上,你只需要决定所需的最小功能。

0

如果我担心模糊内部表示我的数据给外部用户,我会使用XML或JSON。无论哪种方式,它们都相当普遍。

+0

是否意味着字符串返回类型总是? – erdogany 2010-05-27 08:59:12

+0

当然。 XML和JSON意图是非常普遍的,什么可能比字符串更普遍? – Cyberherbalist 2010-05-27 20:19:46

+2

那么,如果我在应用程序之间传递数据,我将使用这种编码。但是,如果我正在谈论函数的返回值...将其转换为XML,将其作为String返回,然后调用者必须解析XML?这仅仅是为了返回一个数组而非常复杂和繁琐。 – Jay 2010-05-28 14:44:06

1

是的,如果您的第一个替代方法不是您的接口合约的一部分,并且该方法总是返回List,那么它会泄漏实现细节。此外,允许用户代码替换您的集合实例有点危险,因为它们传递的实现可能不像您期望的那样运行。

当然,这完全取决于您对用户的信任程度。如果你把Python哲学称作“我们都在这里同意大人”,那么第一种方法就好了。如果你认为你的图书馆会被没有经验的开发者使用,你需要尽一切可能“照顾”他们,并确保他们不会做错什么,那么最好不要让他们设置收集,甚至不要让他们返回实际收集。而是返回一个(浅)副本。

+1

java.util.Collections包含像unmodifiableList()这样的静态方法,它只是简单地包装集合,以便所有修改集合的方法都会返回错误。由于实例化包装器是一个常量操作,因此即使是浅拷贝也是可取的(如果客户端代码需要可变集合,它可以自己生成)。 – 2010-06-05 18:14:28

0

这取决于您希望提供给用户的保证。如果数据是连续的,以便元素的顺序很重要,并且允许重复,则使用列表。如果元素的顺序无关紧要,可能会或可能不允许重复,请使用集合。既然你实际上返回了底层集合,你不应该同时拥有一个get和set函数,只有一个get函数,因为返回的集合可能会发生变异。此外,提供设置功能允许用户更改集合类型,而您可能希望特定类型由您控制。

5

使用最通用的类​​型,即集合,除非有一些明确的理由使用更具体的类型 - 列表,否则最有意义。但是无论你做什么,如果这是公共消费的API,请在文档中明确它的作用;如果它返回集合的浅表副本如此说。

7

当返回一个接口或类在高层次结构中的实现时,经验法则是声明的返回类型应该是最高级别,它提供了准备保证给调用者的最小功能,而且呼叫者合理需要。例如,假设你真正返回的是一个ArrayList。 ArrayList实现List和Collection(除其他外)。如果你期望调用者需要使用get(int x)函数,那么它不会返回一个Collection,你需要返回一个List或者ArrayList。只要你没有看到任何理由,为什么你会改变你的实现来使用列表以外的其他东西 - 比如一个Set - 那么正确的答案是返回一个List。我不确定ArrayList中是否存在不在List中的任何函数,但如果存在,则会应用相同的推理。另一方面,一旦你返回一个List而不是一个Collection,你现在已经在某种程度上锁定了你的实现。您放入API越少,您对未来改进的限制就越少。

(在实践中,我几乎总是返回在这种情况下一个列表,它从来没有烧掉了我,但我可能真的应该返回一个Collection)

9

的能力索引通过列表名单独立.get(int),那么用户(或您)是否期望集合中的元素处于可靠和可预测的顺序?收藏品可以有多个相同的物品?这些都是对更普通的集合不常见的列表的期望。这些是我在确定要向最终用户公开哪个抽象时使用的测试。

14

返回列表符合最高适用界面的编程。

返回集合会导致用户模糊不清,因为返回的集合可能是:Set,List或Queue。

相关问题