java - 应该删除(Object) 为删除(? super E)

标签 java generics collections super contravariance

this answer ,我试图解释为什么 Collection 方法 add 具有签名 add(E)removeremove(Object).我想出了正确的签名应该是

public boolean remove(? super E element)

由于这在 Java 中是无效语法,因此他们必须坚持使用 Object,而它恰好是 super E(E 的父类(super class)型) >) 对于任何 E。以下代码解释了为什么这是有意义的:

List<String> strings = new ArrayList();
strings.add("abc");

Object o = "abc"; // runtime type is String
strings.remove(o);

由于运行时类型是 String,因此成功。如果签名是remove(E),这会在编译时导致错误,但不会在运行时导致错误,这是没有意义的。但是,以下应该在编译时引发错误,因为该操作因其类型而注定会失败,而这些类型在编译时是已知的:

strings.remove(1);

remove 采用 Integer 作为参数,它不是 super String,这意味着它可以永远不要真正从集合中删除任何内容。

如果 remove 方法是使用参数类型 定义的? super E,编译器可以检测到类似上述情况。

问题:

我的理论是否正确,即 remove 应该有一个逆变 ? super E 参数而不是 Object,这样编译器就可以过滤掉上面示例中所示的类型不匹配? Java 集合框架的创建者选择使用 Object 而不是 是否正确? super E 因为 ? super E 会导致语法错误,他们只是同意使用 Object 而不是 super,而不是使通用系统复杂化?

此外,removeAll 的签名应该是

public boolean removeAll(Collection<? super E> collection)
<小时/>

请注意,我不想想知道为什么签名不是remove(E),这在 this question 中被询问和解释。 。我想知道 remove 是否应该是逆变的(remove(? super E)),而 remove(E) 表示协方差。

<小时/>

此方法不起作用的一个示例如下:

List<Number> nums = new ArrayList();
nums.add(1);
nums.remove(1); // fails here - Integer is not super Number

重新考虑我的签名,它实际上应该允许 E 的子父类(super class)型。

最佳答案

这是一个错误的假设:

because the operation is bound to fail because of its types, which are known at compile-time

这与 .equals 接受对象的道理相同:对象不一定需要具有相同的类才能相等。考虑这个具有 List 不同子类型的示例,如 the question @Joe linked 中指出的。 :

List<ArrayList<?>> arrayLists = new ArrayList<>();
arrayLists.add(new ArrayList<>());

LinkedList<?> emptyLinkedList = new LinkedList<>();
arrayLists.remove(emptyLinkedList); // removes the empty ArrayList and returns true

使用您提议的签名是不可能实现这一点的。

关于java - 应该删除(Object) 为删除(? super E),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30784598/

相关文章:

java - 按边缘排列 Swing 组件

java - 获取http变量JSF

c# - 将泛型方法转换为异步导致泛型参数出现问题

swift - 使用泛型下载的方法需要更多上下文

java - 许多Java集合都实现了add方法——它们实际上是深复制

java - 在 Java 中插入字符串的一部分

java - 在 Android 应用程序中从远处创建环形路线

java - Typesafe Map 的多种键类型

c# - DictionaryBase 和 Dictionary<Tkey,Tvalue> 的区别

java - java中hibernate使用的java列表接口(interface)的语法?