Java – Understanding JAVA generic keyword ‘super’

genericsjava

Recently some people said that I was wrong when I explained why one cannot insert a Number object into a list declared as List<? super RationalNumber>.
(This assumes that RationalNumber is a subclass of Number)

My explanation was that in List<? super RationalNumber> the <? super RationalNumber> stands for an unknown super class of RationalNumber. This means that <? super RationalNumber> indicates that a valid object for List<? super RationalNumber> is an object that extends an unknown super class of RationalNumber.

Since an unknown super class of RationalNumber is really unknown (e.g. it can be an interface X instead of Number), there is not guarantee that Number is a sub-class of X i.e. implements X, so Number is not a valid substitution of <? super RationalNumber>.

What is wrong with this explanation?
Edit: Note that I am asking for what wrong with the way I explain, my explanation. Not another explanation for the original question.

Thanks.

Best Answer

List<? super RationalNumber> is a list of some type X that is a superclass of RationalNumber. Your assumption is that RationalNumber is a subclass of Number, so the possible candidates for X are RationalNumber, Number, or Object. The most restrictive possibility is that X is RationalNumber itself. A List<RationalNumber> can contain only instances of RationalNumber, and cannot contain instances of Number.

In short, a List<? super T> is a list that can accept instances of T, but the current contents are of unknown type. This contrasts with List<? extends T>, which contains instances of T, but does not allow adding new elements because the type accepted is unknown.

This example illustrates the use of super:

void storePies(List<? super RationalNumber> list) { 
    list.add(new RationalNumber(22, 7))
    list.add(new RationalNumber(355, 113))
}

...
List<Number> list = new ArrayList<Number>();
storePies(list);
list.add(3.14159265358979);

This example illustrates the use of extends:

double sum(Collection<? extends Number> numbers) {
    double s = 0;
    for (Number n: numbers) { s += n.doubleValue(); }
    return s;
}

List<Integer> somePrimes = new ArrayList<Integer>();
somePrimes.add(5);
somePrimes.add(17);
double total = sum(somePrimes);
Related Topic