33

本着最佳实践的精神:总是返回一个____,而不是一个____,在我即将从 JDK1.4.2 迁移到 JDK5 等时,我面临着类似的问题。(是的,我知道JDK1.4.2 已停产! ;-))。

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

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

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

现在,在 JDK5 及更高版本中,我可以根据需要使用List<MyObject>

选择 returnMyObject[]而不是 List 或Collection<MyObject>在 java5 中编码的充分理由是什么?

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

  • 对返回的集合强制执行只读属性?(没有add()remove()可能)
  • 对返回的集合强制执行不可变的方面?(即使该集合的引用也不能修改)

PS:JavaGenericFAQ没有那个。

4

4 回答 4

37

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

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

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

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

于 2008-10-22T12:51:50.150 回答
11

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

前任:

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());
}
于 2008-11-10T07:52:01.907 回答
4

查看Collections类中的 unmodifiable* 方法以使返回的集合成为只读/不可变的。这会将原始集合包装在一个列表中,以防止访问更改列表本身(尽管元素本身不是不可变的)。

例如不可修改列表。

对我来说,这取决于如何使用返回的列表。它被传递给哪些其他方法,它将如何使用?一般来说,我更喜欢通用集合而不是数组,但会根据具体情况进行更改。

如果您正在做一些关键的事情,该阵列可能也会执行得更快。

于 2008-10-22T12:53:45.093 回答
3

我的回答被否决了,因为我在课堂上使用代理,并且禁止使用那些东西(代理和反射),因为它会影响某些人的思想表现(很多人甚至不使用反射,但是他们使用休眠和弹簧,它们使用反射,类代理和xml)。

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

于 2008-10-23T13:41:26.323 回答