为什么在泛型中需要“?extends”

时间:2010-03-04 22:42:53

标签: java generics

有没有人能够很好地解释为什么必须在泛型中使用? extends语法?我知道语法强制执行的内容,但它似乎与在Java中完成非泛型类型检查的方式不一致。例如:

void someMethod() {
    List<String> strings = new ArrayList<String>();
    doSomethingWithStrings(strings);
    doSomethingWithObjects(strings); // << This doesn't compile
}

void doSomethingWithStrings(Collection<String> strings) {}

void doSomethingWithObjects(Collection<Object> objects) {}

在注释时会出现编译错误,而在下一个示例中显然没有编译错误:

void someOtherMethod() {
    String string = "worksInBothPlaces";
    doSomethingWithAString(string);
    doSomethingWithAObject(string);
}

void doSomethingWithAString(String string) {}

void doSomethingWithAObject(Object object) {}

我知道可以通过将第二个签名更改为

来修复第一个块
void doSomethingWithObjects(Collection<? extends Object> objects) {}

但是,这似乎与其他地方的类型检查不一致。是否有一些明确的例子,如果没有? extends某些泛型类会更难甚至无法编写。

2 个答案:

答案 0 :(得分:3)

基本上,通用无法确认重新分配的内容。

void AddSomething(Collection<Stuff> object)
{
  object.Add(new Stuff());
}
如果您尝试拨打

将失败

AddSomething(new Collection<ChildStuff>())

因为您无法将一个Stuff添加到ChildStuff集合中。

对于编译器/运行时/无论如何知道你的函数不会做那样的事情,需要告诉它接受子类型是可以的,并且这是通过? extends语法完成的。

答案 1 :(得分:1)

非常简单,因为Collection<String>Collection<Object>的类型不同,并且它也不是它的子类型。

Collection<String> 不是 Collection<Object>,而String Object

关于为什么会出现这种情况的详细信息非常复杂,最好通过参考Angelika Langer's关于Java中泛型的常见问题解答来提供服务。