为什么是 List<Number>不是 List<Object> 的子类型? [英] Why is List<Number> not a sub-type of List<Object>?
问题描述
public void wahey(List<Object> list) {}
wahey(new LinkedList<Number>());
对方法的调用不会进行类型检查.我什至不能按如下方式转换参数:
The call to the method will not type-check. I can't even cast the parameter as follows:
wahey((List<Object>) new LinkedList<Number>());
根据我的研究,我发现不允许这样做的原因是类型安全.如果允许我们执行上述操作,那么我们可以拥有以下内容:
From my research, I have gathered that the reason for not allowing this is type-safety. If we were allowed to do the above, then we could have the following:
List<Double> ld;
wahey(ld);
在方法 wahey 中,我们可以向输入列表添加一些字符串(因为参数维护一个 List
引用).现在,在方法调用之后,ld 引用了一个类型为 List
的列表,但实际列表包含一些 String 对象!
Inside the method wahey, we could add some Strings to the input list (as the parameter maintains a List<Object>
reference). Now, after the method call, ld refers to a list with a type List<Double>
, but the actual list contains some String objects!
这似乎与没有泛型的 Java 正常工作方式不同.例如:
This seems different to the normal way Java works without generics. For instance:
Object o;
Double d;
String s;
o = s;
d = (Double) o;
我们在这里所做的基本上是一样的,除了这将通过编译时检查并且仅在运行时失败.带有列表的版本将无法编译.
What we are doing here is essentially the same thing, except this will pass compile-time checks and only fail at run-time. The version with Lists won't compile.
这让我相信这纯粹是关于泛型类型限制的设计决定.我希望得到一些关于这个决定的评论?
This leads me to believe this is purely a design decision with regards to the type restrictions on generics. I was hoping to get some comments on this decision?
推荐答案
您在没有泛型"示例中所做的是强制转换,这清楚地表明您正在做一些类型不安全的事情.与泛型等效的是:
What you are doing in the "without generics" example is a cast, which makes it clear that you are doing something type-unsafe. The equivalent with generics would be:
Object o;
List<Double> d;
String s;
o = s;
d.add((Double) o);
其行为方式相同(编译,但在运行时失败).不允许您询问的行为的原因是因为它会允许隐式 类型不安全的操作,这些操作在代码中更难注意到.例如:
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 implicit type-unsafe actions, which are much harder to notice in code. For example:
public void Foo(List<Object> list, Object obj) {
list.add(obj);
}
这看起来非常好并且类型安全,除非你这样称呼它:
This looks perfectly fine and type-safe until you call it like this:
List<Double> list_d;
String s;
Foo(list_d, s);
这看起来也是类型安全的,因为您作为调用者不一定知道 Foo 将如何处理其参数.
Which also looks type-safe, because you as the caller don't necessarily know what Foo is going to do with its parameters.
因此,在这种情况下,您有两个看似类型安全的代码,但它们最终却是类型不安全的.这很糟糕,因为它是隐藏的,因此难以避免且难以调试.
So in that case you have two seemingly type-safe bits of code, which together end up being type-unsafe. That's bad, because it's hidden and therefore hard to avoid and harder to debug.
这篇关于为什么是 List<Number>不是 List<Object> 的子类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!