在jdk1.2版本之后的Collection接口被泛型化了,add方法的参数类型为泛型,remove方法的参数类型依然为Object,既然add添加元素时严格限制类型,保证了列表元素结构不被破坏,remove删除却放宽了类型限制,有点不合常理,查阅资料,了解到这样做的原因既有逻辑上的考虑,也有技术上的妥协,可能当时没有更好的解决办法。
一、从remove方法含义上看
在jdk文档中remove(Object o)方法被描述为"removes an element e such that (o==null ? e==null : o.equals(e))",翻译过来就是如果指定删除的元素o是空,那么删除容器中也为空的元素e,如果o不为空,那么删除o.equals(e)等于true的元素e。这段话有两个判断,要么o和e都为空,要么o.equals(e),这两个判断中都没有对o和e的类型做限制,o和e都为空很好理解,另外o.equals(e)的equal方法继承自Object,判断两个对象是否相等没有类型限制。所以remove方法并不是要删除和容器内元素类型相同的元素,只要equal方法返回true成立,则删除容器元素。
二、通配符的使用
public class SuperClass {
}
public class SubClass extends SuperClass{
}
public class MyCollection<T> {
public void remove(T t){
System.out.println("remove t from mycollection");
}
public static void main(String[] args) {
MyCollection<? extends SuperClass> myCollection = new MyCollection<SubClass>();
myCollection.remove(new SubClass()); // 无法编译, 只能传入null
}
}
上面代码中,MyCollection类中的remove方法参数是泛型,如果使用通配符声明对象,则无法正常使用remove方法。
三、使用匿名内部类删除
public class SubClass extends SuperClass{
private int num = 0;
public SubClass(int num){
this.num = num;
}
public static void main(String[] args) {
List<SubClass> list = new ArrayList<SubClass>();
list.add(new SubClass(1));
list.add(new SubClass(2));
list.add(new SubClass(2));
list.add(new SubClass(3));
// 删除元素方式一: 循环删除num==2的元素
for(Iterator<SubClass> iterator = list.iterator();iterator.hasNext();){
SubClass sub = iterator.next();
if (sub.num == 2) {
iterator.remove();
}
}
// 删除元素方式二: 使用匿名内部类删除num==2的元素
list.remove(new Object(){
@Override
public boolean equals(Object obj){
SubClass sub = (SubClass)obj;
return 2 == sub.num ? true : false;
}
});
}
}
上面代码中删除容器元素有两种方式,第一种使用迭代器删除,第二种利用了remove方法参数类型是Object,使用匿名内部类覆写了Object的equals方法。
四、使用接口或父类声明对象删除
public class SubClass extends SuperClass implements A{
private int num = 0;
public SubClass(int num){
this.num = num;
}
public static void main(String[] args) {
List<SubClass> list = new ArrayList<SubClass>();
list.add(new SubClass(1));
list.add(new SubClass(2));
list.add(new SubClass(2));
list.add(new SubClass(3));
// 使用接口或父类声明
A a = new SubClass(2);
SuperClass superClass = new SubClass(2);
// 传入接口和父类声明对象
list.remove(a);
list.remove(superClass);
}
}
remove方法参数是Object的另一个好处:可以用接口或父类声明对象,删除该声明实际指向的对象。
总结:
如果remove方法参数是泛型,那么remove方法的含义将发生改变,还有上面的几种删除元素的方式将不能再使用。也许这就是remove方法是Object的原因吧。
👉👉👉 自己搭建的租房网站:全网租房助手,m.kuairent.com,每天新增 500+房源
探讨Java集合中remove方法为何接受Object类型参数,而非泛型。分析remove方法逻辑,展示通配符、匿名内部类及接口删除元素技巧。
1172

被折叠的 条评论
为什么被折叠?



