ConceptDifficulty: Advanced1 min

Bounded Wildcards: ? extends and ? super

Producer extends, consumer super: a wildcard says which way values flow.

A bounded wildcard lets a parameter accept a family of generic types instead of one. ? extends T accepts a collection of T or any subtype, and lets you read Ts out of it. ? super T accepts a collection of T or any supertype, and lets you put Ts into it.

A method that copies invoices from one list into another needs to accept more than one exact type on each side, and the two sides need opposite freedoms:

The two bounded wildcards, on what they accept and what you may do
WrittenAcceptsYou may readYou may add
List<? extends Invoice>A list of Invoice or of any subtypeAn InvoiceNothing
List<? super Invoice>A list of Invoice or of any supertypeAn ObjectAn 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; 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; it does not know what else is in there, so reading gives you Object.

java
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, such as T, where a method both reads and writes.