fas*_*ava 22 java oop generics covariance
我知道为什么不应该这样做.但有没有办法向外行人解释为什么这是不可能的.你可以轻松地向外行解释:Animal animal = new Dog();.狗是一种动物,但是一系列的狗并不是动物的清单.
Bri*_*new 48
想象一下,你创建了一个狗列表.然后将其声明为List <Animal>并将其交给同事.他并非不合理地相信他可以把猫放进去.
然后他把它还给你,你现在有了一份狗的名单,其中有一只猫.随之而来的是混乱.
值得注意的是,由于列表的可变性,这种限制是存在的.在斯卡拉(例如),您可以声明列表狗是列表的动物.那是因为Scala列表(默认情况下)是不可变的,因此将Cat添加到Dogs列表会给你一个新的动物列表.
您正在寻找的答案是与协方差和逆变的概念有关.有些语言支持这些(例如,.NET 4增加了支持),但是这样的代码证明了一些基本问题:
List<Animal> animals = new List<Dog>();
animals.Add(myDog); // works fine - this is a list of Dogs
animals.Add(myCat); // would compile fine if this were allowed, but would crash!
Run Code Online (Sandbox Code Playgroud)
因为Cat将来自动物,所以编译时检查会建议它可以添加到List中.但是,在运行时,您无法将Cat添加到Dogs列表中!
因此,尽管看起来直观简单,但这些问题实际上非常复杂.
这里有一个MSDN概述了.NET 4中的协同/反演:http://msdn.microsoft.com/en-us/library/dd799517(VS.100).aspx - 它也适用于java,尽管我不喜欢知道Java的支持是什么样的.
我能给出的最好的外行答案是:因为在设计泛型时,他们不想重复对Java的数组类型系统做出的相同决定,这使得它不安全.
这可以用于数组:
Object[] objArray = new String[] { "Hello!" };
objArray[0] = new Object();
Run Code Online (Sandbox Code Playgroud)
由于数组类型系统在Java中的工作方式,此代码编译得很好.它会ArrayStoreException在运行时提高.
决定不允许对泛型的这种不安全行为.
另请参见其他地方:Java Arrays Break Type Safety,许多人认为它是Java Design Flaws之一.
你要做的是以下几点:
List<? extends Animal> animals = new ArrayList<Dog>()
Run Code Online (Sandbox Code Playgroud)
这应该工作.