WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.
You may think generics is all about avoiding casts in collections. However, I found a really good use for them the other day that's pretty useful.
Let's say you have a method which takes a List
and does something with it.
void doSomething(List list) {
...
}
(In my code, it's actually
List<String>
, but I'm trying to keep other generics out of this to motivate those of you still needing a good reason to learn them.)
In my case, I needed to iterate over the list in reverse order. Uh oh, that's going to be pretty expensive for some types of lists, and if I switch my implementation to for example a LinkedList
in the future, I'd like to revisit this. Obviously, I could make my method the following:
void doSomething(ArrayList list) {
...
}
However, using specific implementation classes rather than interfaces is frowned upon, and besides, this needlessly prevents the method from being used with other random access list. On the other hand, I would like to state in some way that this method really wants to be able to access the list elements in random order.
java.util.RandomAccess
to the rescue. Lists that provide random access implement this interface. But what do I put in my method signature? RandomAccess
is not itself a List
. I really want to specify multiple constraints on my parameter.
This is precisely what generic methods allow! The following method declaration will accomplish what I want:
<T extends List & RandomAccess> void doSomething(T list) {
...
}
Here we're saying that my parameter T is a generic type, which satisfies multiple constraints: it both extends List
and it implements RandomAccess
! You can pass an ArrayList
to the above method, but not a LinkedList
!
Think hard about the constraints you add. In some cases, adding a RandomAccess
constraint on a method is leaking implementation through to the client - it reveals something about the implementation behind the method signature that may change later. I find this most appropriate within implementation code.