Why boolean containsAll(Collection < ?> c); method of collection framework is allowed for every type ?.But boolean addAll(Collection< ?extends E> c); allow for ? extends E.So,i wrote a program for clarification. Here is my program
public class ContainAllTest {
// take ServiceDto
ArrayList<ServiceDto> resultList = new ArrayList<ServiceDto>();
void Test() {
ServiceDto serviceDto = new ServiceDto();
serviceDto.setName("test");
resultList.add(serviceDto);
// another arraylist that takes String
ArrayList<String> resultList1 = new ArrayList<String>();
resultList1.add("test");
// no error, goes for run time.Contain all checking is done for two generic type ServiceDto and String:
resultList.containsAll(resultList1);
// error shown at compile time,as addAll take ServiceDto as generic type but the generic type for resultList1 take String:
resultList.addAll(resultList1);
}
So,my question is when can i get advantage of resultList.containsAll(resultList1); when the generic type is different.In my case String and ServiceDto.Was there some thing wrong replacing boolean containsAll(Collection< ? > c) with boolean containsAll(Collection< ?extends E> c)
I'm guessing the reason is that containsAll
(and contains
, remove
, removeAll
) uses Object#equals
for the comparison.
You could, conceivably, have an overriden Object#equals
method in E
that can return true
for objects of some unrelated class. Not that it would be a good idea, but it could be a valid implementation.
This isn't to give an advantage it's to save cpu ticks. Generics are erased by the compiler and replaced with casts.
For the addAll
method type safety needs to be taken into account. The user should only be allowed to add a Collection<E>
or some subclass of E
to a Collection<E>
.
If you look at the source code for AbstractCollection
you see this method:
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
When compiled it will look (something) like
public boolean addAll(Collection c) {
boolean modified = false;
for (Object e : c)
if (add((E)e))
modified = true;
return modified;
}
I.e. each and every element of the collection to be added needs to be cast from Object
to E
before being added.
For the containsAll
method it doesn't matter. As the equals
method is defined as equals(Object other)
you can safely call it with any other Collection
and there is no risk of ClassCastException
s. By avoiding the use of generics the compiler can avoid adding in casts.
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