为什么是 List<Number>不是 List<Object> 的子类型? [英] Why is List&lt;Number&gt; not a sub-type of List&lt;Object&gt;?

查看:28
本文介绍了为什么是 List<Number>不是 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆