VonC VonC - 6 days ago 6
Java Question

API java 5 and more: should I return an array or a Collection?

In the spirit of Best Practices: Always return a ____, never a ____, I face a similar question in my upcoming migration from JDK1.4.2 to JDK5 and more. (Yes, I know, JDK1.4.2 is EOL! ;-) ).

For functions returning a collection (which are not simple property collections), I always prefer (in JDK1.4.2) returning an Array instead of a generic List, because:


  • it enforces the returning type (
    MyObject[]
    instead of List of Objects, much more type-safe on a static -- as in 'compilation' -- level)

  • it suggests a 'read-only' character to the returned collection (it is more complicated to add an element to the collection, even though this is not as rigorous as the 'read-only' keyword in c#). This is not the same as saying it is 'immutable' since the references inside the array can still be modified...



Of course, I do always create this returned array (I do not expose any 'internal' array)

Now, In JDK5 and more, I could use
List<MyObject>
if I want to.

What are the good reasons for choosing to return
MyObject[]
instead of List or
Collection<MyObject>
when coding in java5 ?


Bonus, if
Collection<MyObject>
is used, is it possible to:


  • enforce a read-only attribute on the returned collection ? (no
    add()
    or
    remove()
    possible)

  • enforce an immutable aspect to the returned collection ? (even the references of that collection can not be modified)



PS: The JavaGenericFAQ did not quite have that one.

Answer

Prefer Collection (or List, or Set as appropriate) to an array. With generics you get the type-checking that was lacking pre-Java 5. Also, by exposing only the interface, you are free to change the implementation later (e.g. switch an ArrayList for a LinkedList).

Arrays and generics don't mix very well. So, if you want to take advantage of generics, you should usually avoid arrays.
I.e: You can't generically create an array. For example, if T is a generic type then "new T[0]" doesn't compile. You'd have to do something like "(T[]) new Object[0]", which generates an unchecked cast warning. For the same reason, you can't use generic types with varargs without warnings.

Using Collections.unmodifiableCollection (and similar methods), you get the read-only constraint (which you can't achieve with an array - you would have to return a clone of the array).

You can't enforce immutability of members, but then you can't do that with an array either.

Comments