为什么Collection接口的remove方法参数类型是Object而不是类型参数(泛型)

探讨Java集合中remove方法为何接受Object类型参数,而非泛型。分析remove方法逻辑,展示通配符、匿名内部类及接口删除元素技巧。

       在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+房源

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值