API java 5 及更高版本:我应该返回数组还是集合?

2022-09-01 07:36:05

本着最佳实践的精神:始终返回 ____,从不返回 ____,在即将从 JDK1.4.2 迁移到 JDK5 等时,我遇到了类似的问题。(是的,我知道JDK1.4.2是EOL! ;-))。

对于返回集合的函数(不是简单的属性集合),我总是更喜欢(在JDK1.4.2中)返回数组而不是泛型列表,因为:

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

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

现在,在JDK5和更多中,如果我愿意,我可以使用它。List<MyObject>

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

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

  • 对返回的集合强制实施只读属性 ?(否或可能)add()remove()
  • 对返回的集合强制实施不可变方面 ?(即使该集合的引用也无法修改)

PS:JavaGenericFAQ没有这个。


答案 1

首选“集合”(或“列表”,或“根据需要设置”)作为数组。使用泛型,您可以获得Java 5之前缺少的类型检查。此外,通过仅公开接口,您以后可以自由地更改实现(例如,将ArrayList切换为LinkedList)。

数组和泛型不能很好地混合。因此,如果要利用泛型,通常应避免使用数组。
即:您不能一般地创建数组。例如,如果 T 是泛型类型,则“new T[0]”不会编译。你必须做一些类似“(T[])new Object[0]”的事情,这会生成一个未经检查的强制转换警告。出于同样的原因,您不能在没有警告的情况下将泛型类型与 varargs 一起使用。

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

您无法强制成员的不可变性,但也不能对数组执行此操作。


答案 2

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

前任:

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

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

在上述情况下,最好的解决方法是使方法将数组作为其参数,并在将参数传递给它们时使用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());
}