java - 为什么 List<Number> 不是 List<Object> 的子类型?

标签 java generics casting covariance

public void wahey(List<Object> list) {}

wahey(new LinkedList<Number>());

对该方法的调用不会进行类型检查。我什至无法按如下方式转换参数:

wahey((List<Object>) new LinkedList<Number>());

根据我的研究,我发现不允许这样做的原因是类型安全。如果允许我们执行上述操作,那么我们可以拥有以下内容:

List<Double> ld;
wahey(ld);

在 wahey 方法中,我们可以将一些字符串添加到输入列表中(因为参数维护着一个 List<Object> 引用)。现在,在方法调用之后,ld 引用类型为 List<Double> 的列表。 ,但实际列表包含一些 String 对象!

这似乎与没有泛型的 Java 正常工作方式不同。例如:

Object o;
Double d;
String s;

o = s;
d = (Double) o;

我们在这里所做的基本上是同一件事,只是这将通过编译时检查并且只会在运行时失败。带有列表的版本无法编译。

这让我相信这纯粹是关于泛型类型限制的设计决定。我希望得到一些关于这个决定的评论吗?

最佳答案

你在“没有泛型”的例子中所做的是一个转换,这清楚地表明你正在做一些类型不安全的事情。与泛型等效的是:

Object o;
List<Double> d;
String s;

o = s;
d.add((Double) o);

其行为方式相同(编译,但在运行时失败)。不允许您询问的行为的原因是因为它会允许隐式 类型不安全的操作,这在代码中更难注意到。例如:

public void Foo(List<Object> list, Object obj) {
  list.add(obj);
}

在你这样调用它之前,这看起来非常好并且类型安全:

List<Double> list_d;
String s;

Foo(list_d, s);

这看起来也是类型安全的,因为作为调用者的您不一定知道 Foo 将如何处理它的参数。

所以在那种情况下,你有两个看似类型安全的代码位,它们一起最终是类型不安全的。这很糟糕,因为它是隐藏的,因此很难避免并且更难调试。

关于java - 为什么 List<Number> 不是 List<Object> 的子类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1240316/

相关文章:

C++ 转换为基类

java - 在 J2EE 中的上下文监听器中运行线程是否相关?

java - 从泛型类调用的方法将返回什么类型?

C# Is Type in list 问题

c++ - 以隐式方式在不同类型之间进行类型转换

java - 什么时候需要强制转换 'this'?

java - 命令仅在每次重新加载时有效一次

java - Java 运行时环境 : SIGSEGV, libjvm 检测到 fatal error

java - 是否可以使用 java 代码监视文件夹?

c# - 匹配数字类型的通用约束