目前,我正在准备一场考试,我将在两天后写作。在example-questions中我发现了以下问题:
这会编译吗?
FavoritesList<Person> l = new FavoritesList<Contact>();(联系人扩展人员)
我会回答是的,因为如果我有以下条件:
FavoritesList<Person> l = new FavoritesList<Person>();
l.add(new Contact());这很好。为什么在第一个示例中不是很好?
请牢记:联系延伸人!
提前感谢,致以最诚挚的问候
发布于 2013-07-01 03:02:53
这并不好,因为允许它将允许您将其他类型的Person插入到您的Contacts列表中。虽然Contacts的不可变列表“是”Persons的不可变列表是真的,但Contacts的可变列表不是真的-您可以将非Persons插入到Persons的可变列表中,但不能插入到Contacts的可变列表中。
因此,出于安全原因,Java禁止您做这类事情。你可以这样做:
FavoritesList<? extends Person> l = new FavoritesList<Contact>();
这是有效的,因为您不能通过FavoritesList<? extends Person>插入非Contact并破坏您的列表。
其他语言(例如C#,Scala)允许你为你的类型参数提供协方差和逆方差注释,以便更好地控制在这种情况下允许什么转换(例如,如果是协变,你可以将你的类型参数标记为协变,允许Thing<Derived>转换为Thing<Base>),但Java不允许。下面是关于这个主题的C#参考,它可能会让事情变得更清楚:
http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
发布于 2013-07-01 03:04:01
好吧,这是被禁止的,但让我指出原因:
让我们考虑一下:
FavoritesList<Person> l = new FavoritesList<Contact>();有一些操作对于FavoritesList<Person>是允许的,但是对于FavoritesList<Contact>是被禁止的,即添加Person的任何子类,这会破坏FavoritesList<Contact>的约定。
你可能要找的是:
FavoritesList<? extends Person> wildcardedList = new FavoritesList<Contact>();这意味着:这是一个未指定类型?的列表,此列表中的所有元素都属于此类型?,并且我们知道此类型?正在扩展person。注意,这种类型的通配符一开始可能不直观。基本上,他们给你的是这个列表的只读视图。
让我们假设:
class FavoritesList<T>{
void add(T t){...}
}基本上你不能调用:
wildcardedList.add(new Contact()); 也不:
wildcardedList.add(new Contact()); 因为我们不知道Person或Contact是否是未指定类型T。
要做到这一点,你需要在add参数类型中添加通配符,然后就会变得很混乱。
发布于 2013-07-01 03:00:52
这并不好,因为Java语言中的泛型不支持继承,这意味着FavoritesList<Contact>不是FavoritesList<Person>的子类型
看看这个:http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html
https://stackoverflow.com/questions/17393792
复制相似问题