Java Generics PECS – Producer Extends Consumer Super


Java Generics provide flexibility and type safety when dealing with collections and data structures. One of the key ideas within generics is PECS, short for “Producer Extends, Consumer Super.” Championed by Joshua Bloch, this rule assists developers in identifying the most suitable wildcard when dealing with generic types. This article discusses PECS in detail along with associated topics such as covariance, contravariance, and invariance.

Table of Contents:

What are Generics in Java?

A class, interface, or method that works on a typed data structure is called a generic entity.

In Java, generics allow you to create classes, interfaces, and methods that can work with different types of data while maintaining type safety at compile time, eliminating the need for casting and improving the code readability. 

The Object is the parent class of all other classes, and its reference can be used to point to any other object. These types of objects are not type-safe. Hence, generics introduce a type of safety to it by using a specific data type.

Wildcards in Java

In generic code, the question mark (?) is known as the wildcard in generic programming. It represents an unknown type. The wildcard can be used for a variety of situations, such as the type of a parameter, field, or local variable. Unlike arrays, different objects of a generic type are not suitable with each other, not even explicitly. This can be solved by the wildcard if it is used as an actual type parameter.

Java Training

This is comprehensive training course in Java programming language that will make you grow in your software coding career.

quiz-iconquiz-icon



Covariance, Contravariance, and Invariance

In Java Generics, these concepts tell us how the data types are related to each other when they are using the wildcards.

Covariance (? extends T) allows a generic type to be a subtype of the other generic type, i.e., a List<? extends Number> can hold an Integer, Double, or Float value, and it is read-only, meaning that no new elements can be added. 

List<? extends Number> numbers = new ArrayList<Integer>();
Number num = numbers.get(0); // Allowed
// numbers.add(10); // Not allowed

Contravariance (? super T) allows a generic type to be a supertype of another generic type, i.e., a List<? super Integer> can hold an Integer, Number, or an Object value, allowing the elements to be added but taking care of the safe retrieval, i.e., an Object. 

List<? super Integer> numbers = new ArrayList<Number>();
numbers.add(10); // Allowed
Object obj = numbers.get(0); // Reading results in Object

Invariance (No Wildcards) means that a generic type must match exactly, so a List<Number> can only store the Number and not its subtypes like Integer. These rules take care of safety and give flexibility.

List<Number> nums = new ArrayList<>();
nums.add(1); // Allowed
// List<Integer> ints = nums; // Not allowed

What is PECS?

The concept of PECS  is broken into two parts:

1. Producer Extends: If you only produce items from a structure, use <? extends T>

2. Consumer Super: If you only consume items from a structure, use <? super T>

PECS Producer Extends, Consumer Super is a principle in Java Generics that helps in deciding which one to use, extends or super, when dealing with the wildcard types (?).

It was introduced by Joshua Bloch to make the generic code more flexible and secure.

For example, the Mammal class extends the Animal class (The animal class is a superclass of the Mammal class). Cat/Dog class extends the Mammal class (the Mammal class is a superclass of Cat/Dog class).

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.

Example

List<? extends Number> numbers = new ArrayList<Double>();

Number num = numbers.get(0);  //  Allowed (reading)

numbers.add(10);  //writing not allowed

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.

Example

List<? super Integer> numbers = new ArrayList<Number>();

numbers.add(10);  //Allowed (writing)

Integer num = numbers.get(0);  // reading is not safe

Get 100% Hike!

Master Most in Demand Skills Now!

Producing and Consuming

When a collection produces and consumes elements at the same time, PECS (Producer Extends, Consumer Super) does not apply there. Instead, you should use an exact generic type (T) without wildcards, which will allow both reading and writing.

Example: Modifying a List

Output:

Java Generics PECS – Producer Extends Consumer Super

Explanation: The above code is showing both producing (reading) and consuming (writing) in a list. The modifyList method is reading each item from the list and printing it. Then, it is adding a new item to the list. Since the method is doing both reading and writing, it is using List<T> without wildcards. 

Real-World Analogy

Imagine you have two water containers: a larger one and a smaller one.

You cannot pour water from a larger container into a smaller one without spilling.
You CAN ONLY pour water from a smaller container into a bigger one.

So,

  • When you use <? super SomeType>, you are describing a container that is the same size or larger
  • When you use <? extends SomeType>, you are describing a container that is the same size or smaller

Now, you can create it by thinking of Producers and Consumers like this:

A ‘Producer’ is like a container we only pour water from. i.e., we can take water from it, but we cannot add more because we don’t know its exact type
A ‘Consumer’ is like a container we only pour water into. i.e., we can pour water into it, but we don’t know exactly what’s inside, so we must be careful 

Free Online Java Certification Course

This self-paced Java course will help you develop a solid foundation and job-ready skills in Java development.

quiz-iconquiz-icon



Conclusion

PECS is an important concept in Java Generics that helps to ensure safety when working with wildcard types. Producers can only be used for reading, while Consumers can only be used for writing. If both reading and writing are needed, a generic type (T) without wildcards should be used. This makes generic code more flexible and secure, helping Java collections become more efficient and type-safe.

If you want to learn more about Java, you can refer to our Java Course.

Java Generics PECS – FAQs

Q1.What is PECS in Java?

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.

Q2. What is super and super () in Java?

The super keyword in Java is a reference variable that is used to refer to the parent class objects, variables and methods. Whereas, The super()in Java is used to call the parent class constructor. super() can be used to call parent class variables and methods. It can be used to call parent class constructors only.

Q3. How many extends in Java?

In Java, classes may extend only one superclass

Q4. What is a superclass in Java?

The class from which the subclass is derived is called a superclass (also a base class or a parent class).

Q5. What is the difference between extends and super in Java?

Extends keyword adds flexibility to the return types but disables method parameter types. Super keyword adds flexibility to method parameter types but makes return types not useful



Leave a Reply

Your email address will not be published. Required fields are marked *