本着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[]
而不是对象列表,更多 类型安全 对静态 - 如'编译' - - 级别)当然,我总是创建这个返回的数组(我不公开任何'内部'数组)
现在,在JDK5及更多版本中,如果我愿意,我可以使用List<MyObject>
。
在java5中编码时,选择返回MyObject[]
而不是List或Collection<MyObject>
的理由是什么?
奖金,如果使用Collection<MyObject>
,可以:
add()
或remove()
)PS:JavaGenericFAQ并没有那个。
答案 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
类中的不可修改的*方法,使返回的集合为只读/不可变。这会将原始集合包装在一个阻止访问更改列表本身的列表中(虽然元素本身不是不可变的)。
对我而言,这取决于返回列表的使用方式。它传递给了什么其他方法,它将如何使用?一般来说,我更喜欢数组上的泛型集合,但会根据具体情况进行更改。
如果你正在做一些关键的事情,阵列的表现可能会更快。
答案 3 :(得分:3)
我的回答被低估了,因为我使用代理进行上课并且使用这些东西(代理和反射)被禁止,因为它会影响某些人的思维表现(许多人甚至不使用反射,但他们使用休眠和弹簧它使用relfection,类代理和xml)。
来自cglib.sourceforge.net项目的Enhancer,它允许为类创建代理(JDK仅支持接口的代理)。 Proxy允许您控制对象中的方法,但是您无法使用反射访问字段。如果你有问题请问。