Effective Java - Generics
Generics (Ch 5)
This is a short summary of Joshua Blochs book Effective Java chapter 5. I have only included items that I find relevant.
Don’t use raw types (Item 23)
Using unbounded wildcard type is better than using raw types e.g. Set<?>
. This is because you cannot add anything to such collection other than null
, while with a raw type you can add anything. So <?>
are great for readonly collections.
Prefer Lists to Arrays (Item 25)
Arrays are covariants: If A
is subtype of B
, then A[]
is a subtype of B[]
. Generics are invariants: List<A>
is not a subtype of List<B>
. One might think that arrays are more flexible than generics, but they actually complicate code:
Because of these differences, arrays and generics do not mix well, and it is illegal to create generic arrays (e.g new List<E>[]
). Arrays provide runtime safety but not compile time, and vice versa with generics. General advice is to replace arrays with lists when you find you self mixing them. However, if you cannot use lists for example due to performance, there are workarounds, see Item 26.
Bounded wildcards - extend and super (Item 28)
Consider
calling the method with test(new ArrayList<Integer>())
will give compilation error because List<Integer>
is considered a a completely different type than List<Number>
. Changing the signature to use bounded wildcards will fix this:
Note however that this is perfectly valid:
- When to use
extend
and when to usesuper
? Mnemonic for remembering bounded wildcard: PECS - producer-extends, consumer-super- For example for a stack method
pushAll(srcCollection)
the parameter srcCollection produces elements that are used by the stack, hence the method parameter should use<? extends T>
. - On the other hand, a stack method
popAll(destCollection)
the parameter destCollection consumes elements in the stack, hence the method parameter should use<? super T>
.
- For example for a stack method
- Do not use wildcard types as return types!
- If a user of a class has to think about wildcard types, there is probably something wrong with the class’ API.
- All comparables and comparators are consumers!