Why can I use super only with wildcards and not with type parameters?
For example, in the Collection interface, why is the toArray method not written like this
interface Collection<T>{
<S super T> S[] toArray(S[] a);
}
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
superto bound a named type parameter (e.g.<S super T>) as opposed to a wildcard (e.g.<? super T>) is ILLEGAL simply because even if it’s allowed, it wouldn’t do what you’d hoped it would do, because sinceObjectis the ultimatesuperof all reference types, and everything is anObject, in effect there is no bound.In your specific example, since any array of reference type is an
Object[](by Java array covariance), it can therefore be used as an argument to<S super T> S[] toArray(S[] a)(if such bound is legal) at compile-time, and it wouldn’t preventArrayStoreExceptionat run-time.What you’re trying to propose is that given:
and given this hypothetical
superbound ontoArray:the compiler should only allow the following to compile:
and no other array type arguments (since
Integeronly has those 3 types assuper). That is, you’re trying to prevent this from compiling:because, by your argument,
Stringis not asuperofInteger. However,Objectis asuperofInteger, and aString[]is anObject[], so the compiler still would let the above compile, even if hypothetically you can do<S super T>!So the following would still compile (just as the way they are right now), and
ArrayStoreExceptionat run-time could not be prevented by any compile-time checking using generic type bounds:Generics and arrays don’t mix, and this is one of the many places where it shows.
A non-array example
Again, let’s say that you have this generic method declaration:
And you have these variable declarations:
Your intention with
<T super Integer>(if it’s legal) is that it should allowadd(anInteger), andadd(aNumber), and of courseadd(anObject), but NOTadd(aString). Well,Stringis anObject, soadd(aString)would still compile anyway.See also
Related questions
On generics typing rules:
List<Animal> animals = new ArrayList<Dog>()?Listis different fromList<Object>which is different from aList<?>On using
superandextends:Java Generics: What is PECS?extendsconsumersuper“superandextendsin Java Generics<E extends Number>and<Number>?List<? extends Number>data structures? (YOU CAN’T!)