Java Generics With Upper and Lower Bounds Simply Explained
Generics in Java and especially such with upper and lower bounds can be confusing even though they are otherwise very useful.
Here is an example which explains it all well:
import java.util.ArrayList;
import java.util.List;
class A {
}
class B extends A {
}
public class Test {
public static void main(String[] args) {
// First example with upper bound A
List<? extends A> list1 = new ArrayList<A>();
List<? extends A> list2 = new ArrayList<B>();
// List<? extends A> list3 = new ArrayList<Object>(); won't compile
// Second example with lower bound A
List<? super A> list5 = new ArrayList<A>();
List<? super A> list6 = new ArrayList<Object>();
// List<? super A> list5 = new ArrayList<B>(); // won't compile
}
}
We have two classes - A and B. B extends A. We'll use them to test the upper and lower bounds of the wildcard generics in a class called Test with a List object.
To simplify it in short:
- Upper bound is a boundary that includes the specified class or any which it extends.
- Lower bound includes the specified class or any super class to it.
In the first example:
List<? extends A> list1 = new ArrayList<A>();
List<? extends A> list2 = new ArrayList<B>();
// List<? extends A> list3 = new ArrayList<Object>(); won't compile
When the wildcard extends A this means that the accepted objects will be either A or B. B is accepted because it extends A. Object will not be accepted because it doesn't extend A.
In the second example:
List<? super A> list5 = new ArrayList<A>();
List<? super A> list6 = new ArrayList<Object>();
// List<? super A> list5 = new ArrayList<B>(); // won't compile
The wildcard (?) is linked with the keyword super A, this means that classes A or super classes of A (such as Object) will be accepted. However, B is not accepted because it is not a super class to A.