I was recently told that collection should be preferred to List as the return value of an EJB method. The argument is that in general collection is more generic i.e. gives you t
In my opinion, using a Collection
opposed to a more specific interface like a List
or a Set
is meant to be done intentionally. You would be using the Collection
interface for all instances where a more specific interface extends the Collection
interface, i.e. for true collections. But, you cannot do the same for other interfaces like a Map
which represent mappings rather than collections. This would imply that your EJB interface signtaures ought to be thought of very carefully.
As pointed out in the other answer by SJuan, if you intend to return an ordered collection, then you must be using a List
. You can document this behavior of your interface, but that is missing the point; the method signature ought to convey this. Also, note that List
s may contain duplicates, so if you intend to return a collection without duplicates, it makes a lot more sense to return a Set
instead of a List
or a Collection
. To restate my opinion, the collection returned by an EJB method should reflect the properties of the collection accurately as far as possible, without referencing a concrete type; attempting to rely on documentation to convey this might not have the desired results during development of EJB clients.
On the topic of using Arrays, I would recommend avoiding them, especially arrays of type Object[]
. It is easy to abuse these, and convert them into weakly typed data transfer objects, thereby necessitating extensive documentation on how every element of the array ought to be processed. The same advice applies to Collections, but most folks tend to abuse arrays instead of collections, or at least that has been my observation.
The last note leads to the use of generics in collections. If your container (and indirectly the version of the EJB specification) allows you to use generified interfaces for your methods, then do use them for the extra type safety. After all, getting your client to process List<DomainObject>
is a better design decision than letting the client process a List
or a List<Object>
. I would emphasize on the aspect of container support once again, as EJB 2.x interfaces do not support generics (that has been my observation), while EJB 3.x supports generics (but container can choke at deployment or runtime), and would require your local and remote interfaces to be coded in a particular manner; for instance WebLogic 10.3.x requires you to specify the generics in a super interface that is extended as a local/remote interface.
Then you usually have 4 options: List
, Set
, Collection
and Iterable
. There it depends what is the semantics you want to include.
Set
List
Collection
Iterable
(Note: there are some collection interfaces with more specific semantics: Queue
, Deque
, Map
, Bag
, Multiset
, etc. - but it will be fairly obvious when you need to return them)
First, it is not an issue only with EJB. This applies to all method definitions.
In fact, the same is also said of the definition of parameters and variables:
List<String> myList = new ArrayList<String>();
The broader the definition that is made, the more freedom at the time of implementation. Say that I define:
public class Numbers {
public ArrayList getPrimesUnder(int N) {
}
}
Let's say that I find that I can use someone's else library method to do that, but it returns a Vector instead of an ArrayList. Now, I'll have to risk breaking code that calls to my method or I'll have to copy the data from the Vector to an ArrayList. If I had defined the return type as List, I could return any instance of it.
Why not use Collection in this case? Because List is an specialization of Collection that is ordered. If I want to return my results ordered, then I'll use List. If they are not ordered, then Collection suits better.
Collections in general are preferable over arrays, especially since Java5, where they were turned generic. This gives you type safety, and lots of potential extra features which aren't available in arrays (e.g. Set / Queue etc. behaviour) - these are in fact not directly comparable to arrays at all. Among collections, ArrayList
is the direct analogy of an array, and - being implemented on top of an array - its performance is comparable to a native array.
As for Collection vs List (or some other more specific interface), I personally would prefer the more specific interface, as the characteristics and behaviour of e.g. a List vs a Set is very different. In a well designed interface, you should know (and specify) in advance whether you return e.g. a Set, Dequeue or List. If you return a Collection, all your clients can do (apart from adding/removing elements) is to iterate through it, which may not be enough for them.