This one is basically a write-up of a collection of links about Java generics. Yes, I know, it doesn’t get any more boring. Every Java developer knows this by now, and the cool kids have moved to Scala and Clojure. (I’m working on it, too.) But at work I kept seeing that while the idea is simple, using generics in practice in a useful way is not easy for beginners. So I started tidying up a few bits and pieces I had written for colleagues and had that in my drafts for over a year now, and as I think it’s at least a collection of the best references about generics, here it is.
Let me get it out of the way first: every Java developer should know the Generics in the Java programming language tutorial by Gilad Bracha. Definitely study this first, and that might be enough for most people.
If you’re like me and need another round of explanations and examples to fully get the corner cases, Brian Goetz’s two articles on developerworks are great.
The second article addresses the question
Because the language supports both upper- and lower-bounded wildcards, how do we know which one to use, and when?
Goetz answers
There’s a simple rule, called the get-put principle, which tells us which kind of wildcard to use. The get-put principle, as stated in Naftalin and Wadler’s fine book on generics, Java Generics and Collections (see Resources), says: “Use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don’t use a wildcard when you do both.”
Read the article if that concerns you at all, it’s very useful. I particularly like his clear explanation and example for the less often used lower-bounded wildcard:
public static <T extends Comparable<? super T>> void sort(List<T>list) { ... }
Goetz explains the idea behind the wildcard in the example like this:
[…] rather than restricting the domain of sort() to lists whose elements are comparable to themselves, we can go further — we can sort lists of elements that know how to compare themselves to their supertypes, too.
Alternatively we could say the Comparator must be able to compare at least T – if it can compare more, i.e., more generic types, we’ll take that as an added bonus.
Finally, let’s be balanced and mention the big shortcoming of Java generics: the type erasure, i.e., that the generic types are erased by the compiler and are not available at runtime. So, if you have a List and cast it to an untyped List, you can then insert any old Object into it. Mike Stone explains this in detail.