Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java generic wildcards: copy from a producer into a consumer

Last updated: 5 Oct 20265 min read
tutorial
AdvancedBy AITrove Editorial

An extends wildcard permits reading values as a bound; a super wildcard permits writing values of that bound. A copy method can combine both without claiming two lists have the same element type.

Operational contract

The source produces ParcelEvent values or a subtype. The destination consumes ParcelEvent values and may be a list of ParcelEvent or Object. The method rejects a source over 47 entries before changing the destination, then appends each element. It does not promise all-or-nothing delivery: a destination that throws during add may already contain a prefix. When atomic publication matters, build a separate immutable result and replace one owner reference instead. The wildcard bounds express allowed operations at compile time; they do not check runtime business rules on each event.

Failure case

A depot has a List of ScannedParcel values and needs to add them to a List of ParcelEvent values. List<ScannedParcel> cannot be assigned to List<ParcelEvent>, because that would permit adding a different event subtype to the scanned list. The bounded-copy method accepts the two lists safely while keeping ownership of mutation at the destination.

Java code

Java
import java.util.List;

public class ParcelEventCopy {
    public interface ParcelEvent { String parcelId(); }
    public record ScannedParcel(String parcelId) implements ParcelEvent { }

    public static <T extends ParcelEvent> void append(
            List<? extends T> source, List<? super T> destination) {
        if (source.size() > 47) throw new IllegalArgumentException("Batch exceeds 47 events");
        for (T event : source) destination.add(event);
    }
}

Performance and ownership cost

Reading and appending N elements costs O(N) time and O(1) extra application space. A destination array list may occasionally resize, while a linked destination allocates per entry. The size check is a policy cap, not a rollback mechanism.

Common Mistakes

  • Do not treat List<Subtype> as a subtype of List<Supertype>.
  • Do not assume a wildcard copy is transactional if a destination add fails.
  • Do not use a lower-bounded source when the code needs subtype-specific reads.

Connected lessons

java
generics at api boundaries
generic-wildcard-copy-contract
Storage details