1. Overview
In this article, we will learn the differences between Java generics extends vs super. To learn more about other Java topics, refer to these articles.
2. Java generics extends vs super (PECS)
Java generics follow the “PECS” (Producer – extends and Consumer – super) principle.
- Producer – If you want to only retrieve the elements from a generic collection, use
extends
. - Consumer – If you want to only put elements into a generic collection, use
super
. - If you do both retrieve and put operations with the same collection, you shouldn’t use either
extends
orsuper
.
2. Java generics extends – Covariance
The Upper Bounded Wildcards restrict the unknown type to be a specific type or a subtype of that type and is represented using the extends
keyword.
List<? extends Number>
is an example of a bounded wildcard. The ?
stands for an unknown type which is in fact a subtype of Number
. Note that it could be Number
itself, or some subclass. It need not literally extend Number
. We can say that Number
is the upper bound of the wildcard.
The wildcard declaration of List<? extends Number> numberList
means that any of these are legal assignments:
List<? extends Number> numberList = new ArrayList<Number>(); List<? extends Number> numberList = new ArrayList<Integer>(); List<? extends Number> numberList = new ArrayList<Double>();
2.1. Generics extends – Write operation
You can’t add any objects to the extends
generics including any subtype such as Integer
, Double
and super type Number
as well.
Look at the below code. We are trying to assign double
which results in the compilation error.
List<? extends Number> numberList = new ArrayList<Double>(); numberList.add(10.0);The type of the
numberList
is? extends Number
, in the sense an unknown subtype ofNumber
. Since we don’t know what type it is and being unknown, we don’t know if it is anInteger
,Double
. Thus, it prevents assigning values to theextends
generics.Even the below
Number
assignment is not possible (what if it is aDouble
).List<? extends Number> numberList = new ArrayList<Number>(); numberList.add(10);2.2. Generics extends – Read operation
You can read the values from the
extends
generics and assign toNumber
type. Since the values are definitely of typeNumber
, this is allowed.public class MyClass { public static void main(String args[]) { List<? extends Number> numberList = getDoubleValues(); Number value = numberList.get(0); System.out.println(value); } private static ArrayList<Double> getDoubleValues() { ArrayList<Double> doubleList = new ArrayList<Double>(); doubleList.addAll(Arrays.asList(10.5, 9.5, 7.3)); return doubleList; } private static ArrayList<Integer> getIntValues() { ArrayList<Integer> intList = new ArrayList<Integer>(); intList.addAll(Arrays.asList(10, 9, 7)); return intList; } }However, you can’t assign to subtype variables such as
Double
orInteger
. The type of thenumberList
is? extends Number
, in the sense an unknown subtype ofNumber
. Since we don’t know what type it is and being unknown, we can’t assign to subtypes.public static void main(String args[]) { List<? extends Number> numberList = getDoubleValues(); Double value = numberList.get(0); System.out.println(value); }3. Java Generics
super
A lower bounded wildcard restricts the unknown type to be a specific type or a super type of that type.
We express a lower bounded wildcard using the wildcard character (‘?’), following by the
super
keyword, followed by its lower bound:<? super A>
.The wildcard declaration of
List<? super Integer> numberList
means that any of these are legal assignments:List<? super Integer> numberList = new ArrayList<Integer>(); List<? super Integer> numberList = new ArrayList<Number>(); List<? super Integer> numberList = new ArrayList<Object>();3.1. Generics super – Read operation
The type of the
numberList
is? super Integer
, in the sense, an unknown supertype ofInteger
. Since we don’t know what type it is and being unknown, we don’t know if the super type is aNumber
orObject
.You can’t read the values and assign to
Number
orInteger
asnumberList
could be holdingNumber
orObject
super type.List<? super Integer> numberList = getIntValues(); Number value = numberList.get(0); System.out.println(value);As we know, it is legal to assign subtype value to a super type. As the
Object
class doesn’t extend any supertype andNumber
orInteger
are subtypes of anObject
, you can retrieve the list value to anObject
instance.Though
numberList
holdsInteger
orNumber
, both are subtypes ofObject
.public class MyClass { public static void main(String args[]) { List<? super Integer> numberList = getIntValues(); Object value = numberList.get(0); System.out.println(value); } private static ArrayList<Integer> getIntValues() { ArrayList<Integer> intList = new ArrayList<Integer>(); intList.addAll(Arrays.asList(10, 9, 7)); return intList; } }3.2. Generics super – Write operation
You can add an
Integer
or subclass ofInteger
to thenumberList
.List<? super Integer> numberList = new ArrayList<Object>(); numberList.add(50); System.out.println(numberList.get(0));However, you can’t add
Double
,Number
orObject
to thenumberList
.List<? super Integer> numberList = new ArrayList<Object>(); Number number = 10; numberList.add(number); System.out.println(numberList.get(0));4. Conclusion
To sum up, we have learned the differences between Java generics extends vs super. You can find code samples in our GitHub repository.