I've heard the argument that you should use the most generic interface available so that you're not tied to a particular implementation of that interface. Does this logic apply to interfaces like java.util.Collection?
I would much rather see something like the following:
List<Foo> getFoos()
or
Set<Foo> getFoos()
instead of
Collection<Foo> getFoos()
In the last case, I don't know what kind of data set I'm dealing with, whereas in the first two instances I can make some assumptions about ordering and uniqueness. Does java.util.Collection have a usefulness outside of being a logical parent for both sets and lists?
If you came across code that employed Collection when doing a code review, how would you determine whether its usage is justified, and what suggestions would you make for its replacement with a more specific interface?
Best Answer
Abstractions live longer than implementations
In general the more abstract your design the longer it is likely to remain useful. So, since Collection is more abstract that it's sub-interfaces then an API design based on Collection is more likely to remain useful than one based on List.
However, the overarching principle is to use the most appropriate abstraction. So if your collection must support ordered elements then mandate a List, if there are to be no duplicates then mandate a Set, and so on.
A note on generic interface design
Since you're interested in using the Collection interface with generics you may the following helpful. Effective Java by Joshua Bloch recommends the following approach when designing an interface that will rely on generics: Producers Extend, Consumers Super
This is also known as the PECS rule. Essentially, if generic collections that produce data are passed to your class the signature should look like this:
Thus the input type can be E or any subclass of E (E is defined as both a super- and sub-class of itself in the Java language).
Conversely, a generic collection that is passed in to consume data should have a signature like this:
The method will correctly deal with any superclass of E. Overall, using this approach will make your interface less surprising to your users because you'll be able to pass in
Collection<Number>
andCollection<Integer>
and have them treated correctly.