如何在重写的Collections方法中避免未经检查的强制转换?

时间:2009-10-21 12:07:42

标签: java generics collections

我正在进行List实施。因此,我将不得不重写方法

Collection.containsAll(Collection<?> c);
Collection.removeAll(Collection<?> c);
Collection.retainAll(Collection<?> c);

但正如by Sun所述,他们接受任何类型内容的集合(请注意<?>)。因此编译器不会检查集合,而是由我来检查它。但怎么办呢?由于类型擦除,每个元素上的instanceof将不起作用。下一个解决方案是将每个元素强制转换为ClassCastException。看这里:

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

其他两种方法看起来相似。这样可行。但它给了我编译器警告“警告:[unchecked] unchecked cast”!除非我用“@SuppressWarnings("unchecked")”来压缩它,否则它将无法正常编译。

除非我真的需要,否则我不想依赖“@SuppressWarnings("unchecked")”。有没有办法避免它?你会如何实现像containsAll(Collection<?> c)这样的方法?

修改

好的,对不起伙计们,我还不够清楚。我没有延长AbstractList,我不想这样做。我的列表由平衡二叉树实现。我有insert()remove()contains()(实际上搜索叶子)等自己的实现,并且都采用(泛型)类型{{1}的参数}。关键目标是有一个排序列表,可以在迭代过程中进行修改。

那么......我如何避免T中的警告?我要投!

谢谢! craesh

4 个答案:

答案 0 :(得分:9)

当您致电T时,您无需将元素投放到contains(),因为它被定义为boolean contains(Object o)。请注意,您可以询问Collection<String> contains() Integerremove()对象。没有必要的铸造。

Object也需要AbstractList,因此根本不需要任何投射。

顺便说一句:延长List会带走实施{{1}}的大部分无聊工作。

答案 1 :(得分:2)

只是为了澄清对泛型的误解:

  由于类型擦除,

每个元素上的instanceof都不起作用。

不,这不正确。 instanceof 正常工作。 “类型擦除”只是意味着你无法获得通过泛型为你所获得的集合声明的编译时类型 - 但你无论如何都不关心它。

您要检查的是您获得的元素的运行时类型。这是通过instanceof完成的,完全独立于泛型,并且可以正常工作。

当然,正如约阿希姆·绍尔所指出的那样,你甚至不需要检查这个特定情况下的类型,所以无论如何这一点都没有意义......

编辑:

事实上,Java的AbstractCollection就是这样的:

public boolean containsAll(Collection<?> c) {
    Iterator<?> e = c.iterator();
    while (e.hasNext())
    if(!contains(e.next()))
        return false;
    return true;
}

(来自Sun JDK的消息来源)。

因此,您应该尝试继承AbstractList或至少AbstractCollections

答案 2 :(得分:0)

当然,您可以扩展AbstractList以免费获取这些方法,但您也可以迭代this,而不是c

@Override
public boolean containsAll(Collection<?> c) {
    Iterator<T> it = this.iterator();

    while (it.hasNext()) {
        if (!c.contains(it.next())) {
            return false;
        }
    }

    return true;
}

或简单地说:

@Override
public boolean containsAll(Collection<?> c) {
    for (Object o : this) {
        if (!c.contains(o)) {
            return false;
        }
    }

    return true;
}

答案 3 :(得分:0)

如果你不想扩展AbstractList,至少扩展AbstractCollection。那么你根本不需要实现这个方法,这个问题没有实际意义。