不兼容的类型,泛型,<e> </e>

时间:2015-04-12 17:20:34

标签: java generics

我有一个类,它在一组Integer类型元素上返回一个迭代器,类签名是(我为了简洁而删除了访问修饰符):

class EvenIterator implements Iterator<Integer> { .... }

构造函数定义如下:

public EvenIterator(Set<Integer> intSet) { .... }

当我想将一组泛型传递给构造函数时,问题出现了。所以,要充实一点。我有可访问,填充HashSet<E> arbSet

我尝试将该集传递给构造函数;然而,编译器抱怨:

.... new EvenIterator(arbSet);

我收到了这个错误(据我所知):

  

构造函数GenericSet.EvenIterator(HashSet)未定义

所以,我认为是一个合乎逻辑的回答就是说,&#34;很好,我创建了一个新的整数类型的HashSet并将arbSet传递给它的addAll()方法&#34;:

.... new EvenIterator(new HashSet<Integer>().addAll(arbSet));

当然,这并没有解决问题;但是,错误会更好(更具体):

  

方法addAll(Collection&lt;?extends Integer&gt;),类型为AbstractCollection&lt;整数&gt;不适用于参数(HashSet&lt; E&gt;)

大!但是,如果不改变(或重载)EvenIterator的构造函数,我该怎么办呢?有没有雄辩的方法来实现这一目标?或者,如果所有成员都是Integer类型,它会不会像迭代通用列表并提取Integer那样令人不愉快?

3 个答案:

答案 0 :(得分:1)

从根本上说,你正试图做一个不安全的演员。您想要做什么可能在运行时生成ClassCastException。由您(作为程序的开发人员)来确保这不会发生或正确处理这些异常。这就是你得到编译错误的原因。

您可以使用强制转换来避免编译错误,如下所示:

new EvenIterator((Set<Integer>) arbSet);

这会导致编译时警告,因为演员表仍然不安全。

如果你确定这个不安全的演员阵容确实不是代码中的问题,你可以添加:

@SuppressWarnings("unchecked")

到包含方法声明。

但是,从根本上说,在你真正忽略警告之前,你应该知道为什么需要这个演员。


编辑以下是我编写的代码片段,无需警告:

class EvenIterator implements Iterator<Integer> {
    public EvenIterator(Set<Integer> intSet) { }

    @Override
    public boolean hasNext() {
        return false;
    }

    @Override
    public Integer next() {
        return null;
    }

    @Override
    public void remove() { }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        HashSet<?> arbSet = null;
        new EvenIterator((Set<Integer>) arbSet);
    }
}

答案 1 :(得分:0)

它只需要是一个整数的HashSet,而不是任何类型的E。

HashSet<Integer> arbSet

应该被接受。

答案 2 :(得分:0)

您需要的可能是HashSet<E extends Integer>。如果这不是一个选项,那么设计是错误的 - 它只是违背了泛型的目的。如果构造函数需要并期望Integers,那么Java将不允许您传递任意元素的集合 - 而使用addAll的变通方法同样是不可接受的。

Re:构造函数GenericSet.EvenIterator(HashSet)未定义

这是因为虽然HashSet是Set (Hash)Set<E>的子类,但它不是Set<Integer>的子类