Skip to main content
Java

What is PECS (Producer Extends Consumer Super)?

3 mins

two buckets, one being filled with water (Producer, Extends) and the other being emptied (Consumer, Super), symbolizing the roles of producers and consumers in the context of generics

Wildcards in Java Generics #

In the article ‘Wildcards in Java Generics , we learned about generic types in Java and how they allow us to create classes that work with different types. The summary of the article contained the following rules.

Declaration Wildcard Type Reading Writing
List Unbounded Object No
List<? extends Number> Upper-bounded Number No
List<? super Number> Lower-bounded Object Number

PECS stands for Producer Extends Consumer Super. It is a mnemonic that helps us remember these rules and their implications when working with generics in Java.

The PECS mnemonic is split into two parts:

  • Producer Extends: If you only produce items from a structure, use

<? extends T>

  • Consumer Super: If you only consume items from a structure, use

<? super T>

Covariance, Contravariance and Invariance #

Covariance contravariance and invariance are terms used to describe the relationship between types when working with generics. Covariance means that a type can be replaced with a subtype, while contravariance means that a type can be replaced with a supertype. Invariance means that the relationship between types is fixed and cannot be changed.

For Java generics, these terms are related to the use of wildcards.

Wildcard Term Type PECS Replacement
<? extends T> Covariance Upper-bounded Producer Extends subtype
<? super T> Contravariance Lower-bounded Consumer Super supertype
<?> Invariance Unbounded - none

Producer Extends #

The <? extends T> wildcard is used when you only want to produce items from a structure. This means that you will only read items from the structure and never write to it. The extends keyword is used to specify that the wildcard represents a subtype of T.

Here is an example of using the <? extends T> wildcard with a method that prints the elements of a list:

public static void printNumbers(List<? extends Number> listProducer) {
    for (Number number : listProducer) {
        System.out.println(number);
    }
}

So the listProducer parameter in the printNumbers method is a producer of numbers, so it uses the extends keyword to specify that it can produce any type of number.

Consumer Super #

The <? super T> wildcard is used when you only want to consume items from a structure. This means that you will only write items to the structure and never read from it. The super keyword is used to specify that the wildcard represents a supertype of T.

Here is an example of using the <? super T> wildcard with a method that adds elements to a list:

public static void addNumbers(List<? super Number> listConsumer) {
    listConsumer.add(Integer.valueOf(1));
    listConsumer.add(Double.valueOf(2.5));
    listConsumer.add(Float.valueOf(3.0f));
}

In this example, the addNumbers method takes a list of elements that are supertypes of Number. This means that the method can write elements to the list but cannot read from it.

The parameters listConsumer in the addNumbers method is a consumer of numbers, so it uses the super keyword to specify that it can consume any type of number.