Why is List<Number> not a sub-type of List<Object>?
1 2 3 | public void wahey(List<Object> list) {} wahey(new LinkedList<Number>()); |
对方法的调用将不会进行类型检查。我甚至无法将参数强制转换为以下类型:
1 | wahey((List<Object>) new LinkedList<Number>()); |
从我的研究中,我总结出不允许这样做的原因是类型安全。如果允许我们这样做,那么我们可以有以下内容:
1 2 | List<Double> ld; wahey(ld); |
在方法wahey中,我们可以向输入列表添加一些字符串(因为参数维护一个
这与Java没有泛型的正常工作方式不同。例如:
我们在这里所做的基本上是相同的,除了这将通过编译时检查,并且只在运行时失败。带有列表的版本无法编译。
这让我相信这纯粹是一个关于泛型类型限制的设计决策。我希望能得到一些关于这个决定的评论?
(P)What you are doing in the"without genetics"example is a cast,which make it clear that you are doing some type-unsafe.The equivalent with generics would be:(p)字母名称(P)Which behaves the same way(compiles,but fails at runtime).The reason for not allowing the behavior you're asking about is because it would allow implicait type-unsafe actions,which are much harder to notice in code.For example:(p)字母名称(P)This look perfectly fine and type-safe until you call it like this:(p)字母名称(P)Which also look type-safe,because you as the caller don't necessarily know what foo is going to do with its parameters.(p)(P)So in that case you have two seemingly type-safe bits of code,which together end up being type-unsafe.这是坏的,因为它是hidden and therefore hard to avoid and harder to debug。(p)
(P)想想如果这是…(p)字母名称(P)You would be able to add anything of the parent type to the list,which may not be what it was formerly declared as,which as the above example demonstrates,causes all sorts of problems.Thus,it is not allowed.(p)
(P)他们强调,他们的工作不分性别。你想要做的是宣布你的功能像这样:(p)字母名称(P)它们将接受任何扩展目标的清单。You can also do:(p)字母名称(P)This will let you take in lists of some thing that's a subclass of number.(p)(P)I'd recommend you pick up a copy of"Java genetics and collections"by Maurice Naftalin&Amp;Philip Wadler.(p)
(P)There are essentially two dimensions of abstration here,the list abstration and the abstration of its contents.It's perfectly fine to vary along the list abstraction-to say,for instance,that it's a linked list or an arraylist-but it's not fine to further restrict the contents,to say:this(list which holds objects)is a(linked list which holds only numbers).Because any reference that knows it as a(list which holds objects)understands,by the contract of its type,that it can hold any object.(p)(P)This is quite different from what you have done in the non-genetics example code,where you've said:treat this string as if it were a double.You are instead trying to say:treat this(list which holds only numbers)as a(list which holds anything).And it doesn't,and the compiler can detect it,so it doesn't let you get away with it.(p)
布尔奇1(P)What you're observing makes perfect sense when you consider the main purpose of Java generics is to get type incompatibilities to fail at compile time instead of run time.(p)(P)From Java.sun.com(p)布尔奇1
(P)在爪哇,EDOCX1的英文字母0不是一个字幕的EDOCX1的英文字母1,当EDOCX1的英文字母2是一个EDOCX1的英文字幕3。这条规则提供了安全。(p)(P)让我们说我们有一个EDOCX1的英文字母4将成为一个字母5的字幕。Consider the following example:(p)字母名称(P)So,forcing this provides type safety but it also has a drawback,it's less flexible.Consider the following example:(p)字母名称(P)在这里,你有一个集邮的EDOCX1的英文本3,你想Add所有的项目从另一个集邮。你不能用一个EDOCX1为一个EDOCX1的音标7,一个EDOCX1ideally,this is ok because you are only adding elements into your collection,you are not modifying the parameter collection.(p)(P)To fix this,Java provides what they call"wildcards".威尔德卡斯是一种提供共同变量/反变量的方法。Now consider the following using wildcards:(p)字母名称(P)Now,with wildcards we allow covariance in the type t and we block operations that are not type safe(for example adding an item into the collection).这是我们获得灵活性和类型安全的方式。(p)