This is part of the Java (1.6) Collection interface:
public interface Collection<E> extends java.lang.Iterable<E> {
/* ... */
boolean containsAll(java.util.Collection<?> objects);
boolean addAll(java.util.Collection<? extends E> es);
boolean removeAll(java.util.Collection<?> objects);
boolean retainAll(java.util.Collection<?> objects);
/* ... */
}
Why does addAll
have <? extends E>
while removeAll
has <?>
I did not know, I googled. I got this explaination here: http://www.ibm.com/developerworks/java/library/j-jtp01255/index.html
Copying the part:
One element of the generifed Collections API that is often confusing at first is the signatures of containsAll(), removeAll(), and retainAll(). You might expect the signatures for remove() and removeAll() to be:
interface Collection<E> { public boolean remove(E e); // not really public void removeAll(Collection<? extends E> c); // not really }
But it is in fact:
interface Collection<E> { public boolean remove(Object o); public void removeAll(Collection<?> c); }
Why is this? Again, the answer lies in backward compatibility. The interface contract of x.remove(o) means "if o is contained in x, remove it; otherwise, do nothing." If x is a generic collection, o does not have to be type-compatible with the type parameter of x. If removeAll() were generified to only be callable if its argument was type-compatible (
Collection<? extends E>
), then certain sequences of code that were legal before generics would become illegal, like this one:// a collection of Integers Collection c = new HashSet(); // a collection of Objects Collection r = new HashSet(); c.removeAll(r);
If the above fragment were generified in the obvious way (making c a
Collection<Integer>
and r aCollection<Object>
), then the code above would not compile if the signature of removeAll() required its argument to be aCollection<? extends E>
, instead of being a no-op. One of the key goals of generifying the class libraries was to not break or change the semantics of existing code, so remove(), removeAll(), retainAll(), and containsAll() had to be defined with a weaker type constraint than they might have had they been redesigned from scratch for generics.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With