API java 5及更多:我应该返回数组还是Collection?

时间:2008-10-22 12:39:55

标签: java arrays api generics collections

本着Best Practices: Always return a ____, never a ____的精神,我在即将到来的migration from JDK1.4.2 to JDK5 and more中面临着类似的问题。 (是的,我知道JDK1.4.2 is EOL! ;-))。

对于返回集合的函数(非简单property collections),我总是更喜欢(在JDK1.4.2中)返回一个Array而不是一个通用List,因为:

  • 它强制执行返回类型(MyObject[]而不是对象列表,更多 类型安全 对静态 - 如'编译' - - 级别)
  • 建议返回集合的'只读'字符(将一个元素添加到集合中会更复杂,即使这不像'只读'那么严格c#中的关键字。这与说“不可变”不同,因为数组中的引用仍然可以被修改......

当然,我总是创建这个返回的数组(我不公开任何'内部'数组)

现在,在JDK5及更多版本中,如果我愿意,我可以使用List<MyObject>

在java5中编码时,选择返回MyObject[]而不是List或Collection<MyObject>的理由是什么?

奖金,如果使用Collection<MyObject>,可以:

  • 对返回的集合强制执行只读属性? (不可以add()remove()
  • 对返回的集合强制执行不可变的方面? (甚至不能修改该集合的引用)

PS:JavaGenericFAQ并没有那个。

4 个答案:

答案 0 :(得分:37)

首选集合(或List,或适当设置)到数组。使用泛型,您可以获得缺少Java 5之前的类型检查。此外,通过仅公开接口,您可以稍后更改实现(例如,为LinkedList切换ArrayList)。

阵列和泛型不能很好地混合。所以,如果你想利用泛型,你应该通常避免数组 即:你不能一般地创建一个数组。例如,如果T是泛型类型,则“new T [0]”不会编译。您必须执行类似“(T [])new Object [0]”的操作,它会生成未经检查的强制转换警告。出于同样的原因,您不能在没有警告的情况下使用带有varargs的泛型类型。

使用Collections.unmodifiableCollection(以及类似方法),您将获得只读约束(使用数组无法实现 - 您必须返回数组的克隆)。

你不能强制成员的不变性,但是你也不能用数组做到这一点。

答案 1 :(得分:11)

实际上,数组仍然比收藏/列表有一个优势。由于Java通过类型擦除实现泛型的方式,你不能有两种方法将Collections作为参数,但只有Collection的泛型类型不同。

例如:

public void doSomething(Collection<String> strs) { ... }
public void doSomething(Collection<Integer> ints) { ... }

上述两种方法无法编译,因为javac编译器使用类型擦除,因此无法将类型信息传递给JVM。 JVM只会看到两个以Collection作为参数的方法。

在上面的例子中,最好的解决方法是使方法将数组作为参数,并在将参数传递给它们时使用Collection / List的toArray()方法。如果你仍想在上面的方法中使用Collection / List,只需使用java.util.Arrays.asList()方法来恢复你的List。

例如:

public void doSomething(String[] strs) {
        List<String> strList = Arrays.asList(strs);
        ...
}

public void doSomething(Integer[] ints) {
        List<Integer> intList = Arrays.asList(ints);
        ...
}

public static void main(String[] args) {
        List<String> strs = new ArrayList<String>();
        List<Integer> ints = new ArrayList<Integer>();
        obj.doSomething(strs.toArray());
        obj.doSomething(ints.toArray());
}

答案 2 :(得分:4)

检查Collections类中的不可修改的*方法,使返回的集合为只读/不可变。这会将原始集合包装在一个阻止访问更改列表本身的列表中(虽然元素本身不是不可变的)。

例如

unmodifiableList

对我而言,这取决于返回列表的使用方式。它传递给了什么其他方法,它将如何使用?一般来说,我更喜欢数组上的泛型集合,但会根据具体情况进行更改。

如果你正在做一些关键的事情,阵列的表现可能会更快。

答案 3 :(得分:3)

我的回答被低估了,因为我使用代理进行上课并且使用这些东西(代理和反射)被禁止,因为它会影响某些人的思维表现(许多人甚至不使用反射,但他们使用休眠和弹簧它使用relfection,类代理和xml)。

来自cglib.sourceforge.net项目的Enhancer,它允许为类创建代理(JDK仅支持接口的代理)。 Proxy允许您控制对象中的方法,但是您无法使用反射访问字段。如果你有问题请问。