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

API java 5及更多:我应该返回数组还是集合?,java,arrays,api,generics,collections,Java,Arrays,Api,Generics,Collections,本着这种精神,我在即将到来的演讲中也面临着类似的问题。(是的,我知道,;-)) 对于返回集合(并不简单)的函数,我总是更喜欢(在JDK1.4.2中)返回数组而不是泛型列表,因为: 它强制执行返回类型(MyObject[]而不是对象列表,更重要的是在静态上执行类型安全,如在“编译”级别) 它向返回的集合建议一个“只读”字符(向集合中添加元素更为复杂,尽管这不如c#中的“只读”关键字严格)。这与说它是“不可变”不同,因为数组中的引用仍然可以修改 当然,我总是创建这个返回的数组(我不公开任何“内部

本着这种精神,我在即将到来的演讲中也面临着类似的问题。(是的,我知道,;-))

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

  • 它强制执行返回类型(
    MyObject[]
    而不是对象列表,更重要的是在静态上执行类型安全,如在“编译”级别)
  • 它向返回的集合建议一个“只读”字符(向集合中添加元素更为复杂,尽管这不如c#中的“只读”关键字严格)。这与说它是“不可变”不同,因为数组中的引用仍然可以修改
当然,我总是创建这个返回的数组(我不公开任何“内部”数组)

现在,在JDK5和更多版本中,如果我愿意,我可以使用
List

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

如果使用了
收集
,是否可以:

  • 是否对返回的集合强制执行只读属性?(无
    add()
    remove()
    可能)
  • 对返回的集合强制一个不可变的方面?(即使该集合的引用也无法修改)
PS:没有。比起数组,更喜欢集合(或列表,或根据需要设置)。使用泛型,您可以获得Java 5之前所缺乏的类型检查。此外,通过仅公开接口,您可以在以后自由更改实现(例如,将ArrayList切换为LinkedList)


数组和泛型不能很好地混合。因此,如果您想利用泛型,通常应该避免使用数组。

也就是说:你不能一般地创建一个数组。例如,如果T是泛型类型,则“新T[0]”不会编译。您必须执行类似于“(T[])new Object[0]”的操作,这将生成未经检查的强制转换警告。出于同样的原因,您不能在没有警告的情况下对varargs使用泛型类型

使用(和类似的方法),您将获得只读约束(这是使用数组无法实现的,您必须返回数组的克隆)


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

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

比如说

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


如果你在做一些关键的事情,数组可能也会执行得更快。

我的答案被否决,因为我在类中使用代理,而使用这些东西(代理和反射)是被禁止的,因为它会影响一些人的思维表现(许多人甚至不使用反射,但是他们使用hibernate和spring,它们使用重新过滤、类代理和xml)


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

实际上,数组与集合/列表相比仍有一个优势。由于Java通过类型擦除实现泛型的方式,您不能有两个将集合作为参数的方法,但它们之间的区别仅在于y集合的泛型类型

例:

public void doSomething(集合strs){…}
公共无效doSomething(集合整数){…}
上述两个方法不会编译,因为javac编译器使用类型擦除,因此无法将类型信息传递给JVM。JVM将只看到两个以集合为参数的方法

在上述情况下,最好的解决方法是使这些方法将数组作为其参数,并在向它们传递参数时使用Collection/List的toArray()方法。如果您仍然希望在上述方法中使用Collection/List,只需使用java.util.arrays.asList()方法即可取回列表

例:

public void doSomething(字符串[]strs){
List strList=Arrays.asList(strs);
...
}
公共void doSomething(整数[]整数){
List intList=Arrays.asList(ints);
...
}
公共静态void main(字符串[]args){
List strs=new ArrayList();
List ints=new ArrayList();
目标剂量测量(标准toArray());
目标剂量测量(ints.toArray());
}

谢谢!+1现在(我将等待其他答案)。你可以看出我还没有认真阅读JDK6 javadoc…;)“数组和泛型混合得不好。因此,如果你想利用泛型,通常应该避免使用数组。”->Urg?你能解释一下这部分吗?我的数组与我的泛型很好地混合…你不能泛型地创建数组。例如,如果T是泛型类型,则“新T[0]”不会编译。您必须执行类似于“(T[])new Object[0]”的操作,这将生成未经检查的强制转换警告。出于同样的原因,您不能在没有警告的情况下对varargs使用泛型类型。此处不涉及实时进程。集合不代表“属性”,只代表计算值。感谢您提供的代码和精度+1,但我可能不会很快在我的代码中使用这种额外的层…我理解,但我真正想说的是,它就像使用Collections.unmodifiableCollection。它不会给你任何东西,直到你的收藏不是由你修改。
public void doSomething(Collection<String> strs) { ... }
public void doSomething(Collection<Integer> ints) { ... }
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());
}