接受通用集中的子类型

时间:2012-01-31 19:33:46

标签: java generics

我正试图找到一种方法,我可以返回一个通用集,它将接受子类型。以下代码返回Set<? extends A>,我正在尝试添加B

import java.util.Set;
import java.util.HashSet;

public class Test {
    private static class A {}
    private static class B extends A {}

    public Set<? extends A> getSet() {
        return new HashSet<B>();
    }

    public void work() {
        getSet().add(new B()); // compile error
    }
}

导致以下错误:

Test.java:13: cannot find symbol
symbol  : method add(Test.B)
location: interface java.util.Set<capture#320 of ? extends Test.A>
                getSet().add(new B());

generic wildcard tutorial表示B无法添加到Set<? extends A>,因为我们不知道BA的子类型,但是我刚刚定义它。有人可以为我澄清一下吗?

3 个答案:

答案 0 :(得分:5)

根本不可能。

如果方法实际返回HashSet<C>怎么办? 您刚刚将B添加到一组C s。

检查类型安全时,忽略方法的内容(return语句)。

如果你想这样做,你应该只返回一个普通的HashSet<A>

答案 1 :(得分:0)

问题的关键在于,您可以以这种方式使用通配符来迭代扩展公共父级并执行读取操作的不同对象,但如果要写入集合则不起作用。

原因是编译器无法确定将从getSet()方法返回的集合的运行时类型。它不会解析您编写的代码并尝试做出该决定。

答案 2 :(得分:0)

  

通用通配符教程指出B无法添加到Set&lt;?扩展A>因为我们不知道B是否是A的子类型,但我刚刚将其定义为。

那不太对劲。说B和C各延伸一个。 getSet()方法可能返回一组B或一组C。你不知道。所以你不能只是添加Bs。它可能是一组C,这将破坏合同。

问题不是你不知道B是A的子类型,而是你不知道A的哪个子类型?是