有没有人能够很好地解释为什么必须在泛型中使用? 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
某些泛型类会更难甚至无法编写。
答案 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中泛型的常见问题解答来提供服务。