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

+2


source to share


4 answers


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

.

+9


source


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

+2


source


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;
}

      

0


source


If you don't want to extend AbstractList, at least extend AbstractCollection. Then you don't need to implement this method at all, and it's a moot point.

0


source







All Articles