How to avoid unverified throws in overriding collection methods?
I am working on an implementation List
. Because of this, I will have to override the methods
Collection.containsAll(Collection<?> c);
Collection.removeAll(Collection<?> c);
Collection.retainAll(Collection<?> c);
But, as explained by Sun , they accept collections with any content (note on <?>
). So the compilation is not checked by the compiler and it is up to me to check it. But how to do that? instanceof
for each item won't work due to type erasure. The next solution would be to throw each catch element ClassCastException
. See here:
public boolean containsAll( Collection<?> c ) {
boolean foundAll = true;
for ( Object element : c ) {
try {
foundAll &= this.contains( (T) element );
} catch ( ClassCastException e ) {
foundAll = false;
}
}
return foundAll;
}
The other two methods are similar. It works. But it gives me a compiler warning "warning: [unchecked] unchecked cast"! If I have not suppressed it " @SuppressWarnings("unchecked")
" it will not compile ok.
I don't want to rely on " @SuppressWarnings("unchecked")
" unless I need to. Is there a way to avoid this? How would you implement methods like containsAll(Collection<?> c)
?
change
Okay, sorry guys, I wasn't clear enough. I am not expanding AbstractList
and I donโt want to. My list is implemented by a balanced binary tree. I have my own implementation insert()
, remove()
, contains()
(which actually performs a search on the sheet), etc., and all take an argument (common) type T
. The main goal is to have a sorted list that can be modified as it is iterated over.
So ... how do I avoid the warning in containsAll(Collection <?>)
? I have to quit!
Thank! craesh
source to share
You don't need to highlight your element in T
when you call contains()
, since it is defined as boolean contains(Object o)
. Note that you can set Collection<String>
object contains()
a Integer
. No casting is required there.
remove()
also takes effect Object
, so no casting is required at all.
And by the way: the extension AbstractList
takes away most of the boring implementation work List
.
source to share
Just to clear up the misconception about generics:
instanceof for each element won't work due to type erasure.
No, this is not true. instanceof
will work fine. "Type erasure" means that you cannot get a compile-time type that has been generics declared for the collection you are getting, but that doesn't bother you anyway.
What you want to check is the runtime type of the item you are getting. This is done with instanceof
, is completely generic independent and will work.
Of course, as Joachim Sauer points out, you don't even need to check for type in this particular case, so the point is moot anyway ...
Edit:
Actually Java AbstractCollection does it like this:
public boolean containsAll(Collection<?> c) {
Iterator<?> e = c.iterator();
while (e.hasNext())
if(!contains(e.next()))
return false;
return true;
}
(from Sun JDK sources).
So, you should really be trying to inherit from AbstractList
or at leastAbstractCollections
source to share
of course, you can extend AbstractList
to get these methods for free, but you can also iterate this
instead of c
:
@Override
public boolean containsAll(Collection<?> c) {
Iterator<T> it = this.iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
return false;
}
}
return true;
}
or simply:
@Override
public boolean containsAll(Collection<?> c) {
for (Object o : this) {
if (!c.contains(o)) {
return false;
}
}
return true;
}
source to share