Card 05/ 09
All 9 cards
ConceptDifficulty: Advanced1 min
extends and super: Which Way the Values Are Allowed to Flow
A method that copies from one collection into another needs to accept more than one exact type on each side, and the two sides need opposite freedoms.
| Written | Accepts | You may read | You may add |
|---|---|---|---|
List<? extends Invoice> | A list of Invoice or of any subtype | An Invoice | Nothing |
List<? super Invoice> | A list of Invoice or of any supertype | An Object | An Invoice |
The restrictions follow from what the compiler can know. With ? extends Invoice it knows every element is at least an Invoice, so reading is safe — and it does not know which subtype, so nothing is safe to add. With ? super Invoice it knows the list can hold an Invoice, so adding one is safe — and it does not know what else is in there, so reading gives you Object.
void copy(List<? extends Invoice> from, List<? super Invoice> into) {
for (Invoice invoice : from) {
into.add(invoice);
}
}The mnemonic is producer extends, consumer super: the side you take values out of is extends, and the side you put values into is super.
So a wildcard on a parameter is a statement about direction. Use them on parameters where the direction is one-way, and leave a plain type parameter where a method both reads and writes.