What is a difference between ? super E and ? extends E?
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.
In Java generics, the wildcard symbols <? super E> and <? extends E> play a significant role in defining variable bounds and flexibility for collections and method parameters. Understanding the differences between these two is essential for utilizing Java's generic types effectively.
Introduction to Generics
Generics allow for type safety in Java without the need to define a class for every data type. They enable classes, interfaces, and methods to operate on objects of various types while still providing compile-time type safety.
To understand the constraints introduced by <? super E> and <? extends E>, let's first review what they mean:
<? extends E>: This wildcard allows you to use any class that either matches the typeEor is a subclass ofE.<? super E>: This wildcard allows you to use any class that matches the typeEor is a superclass ofE.
<? extends E>
The <? extends E> wildcard represents an upper bounded wildcard. It's used when you want to ensure that you're dealing with either E objects or objects from subclasses thereof.
Example
To illustrate this point, consider a list of numbers:
In the above example, the processList method can accept a list of type Number or any subclass, such as Integer, Double, or Float. The benefit here is that you can read items from the list — since you know they are at least type Number — but you cannot add new elements, as the exact type is not specified.
Key Points
- Read Access: You can read elements as type
Eor its parent classes. - No Write Access: Writing elements to the collection is disallowed because the exact type cannot be guaranteed.
- Common Use Cases: You see this in APIs where the data flows out of the collection.
<? super E>
The <? super E> wildcard signifies a lower bounded wildcard. This wildcard is useful when adding elements to a structure, enforcing that the structure can handle all objects of type E or any superclass thereof.
Example
Take a scenario where you are adding elements to a list:
Here, the list can be of type Integer, Number, or Object since Integer is a subclass of both Number and Object. Although you can add Integer values to this list, read operations may not directly return the desired type Integer unless explicitly cast, as demonstrated by the commented-out line.
Key Points
- Write Access: You can write into the collection because the type bounds are set from a lower limit down.
- Read Restrictions: You cannot assume the type of the retrieved objects without casting.
- Common Use Cases: This pattern is frequent in APIs where the elements are added to the collection.
Table of Key Differences
| Aspect | <? extends E> | <? super E> |
| Wildcard Type | Upper bounded | Lower bounded |
| Usage | Use when you want to read from a structure | Use when you want to write to a structure |
| Read/Write Permissions | Read permitted, write not permitted (additions) | Write permitted, read requires casting |
| Type Constraints | Any subclass of E | E or any superclass of E |
| Typical Use Cases | Data consumption | Data addition |
Conclusion
Both <? super E> and <? extends E> provide ways to introduce flexibility and type safety into Java applications, but selecting the right one depends on whether you're primarily reading from or writing to a data structure. By effectively leveraging these wildcards, developers can create robust and flexible APIs that accommodate a wide variety of use cases.
Understanding these differences is crucial to mastering Java generics and ensuring that your code can efficiently and safely handle hierarchies of types.
Related reading
- What is a raw type and why shouldn't we use it?
- What is a singleton in C?
- What is Bulkhead Pattern used by Hystrix?
- What is lazy initialization and why is it useful?
- What is a fat JAR?
- What is a good Java library to zip/unzip files?
- What is PECS (Producer Extends Consumer Super)?
- What is the best way of implementing a singleton in Python?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.