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

       在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 {
    
    public void remove(T t){
        System.out.println("remove t from mycollection");
    }
    
    
    public static void main(String[] args) {
        
        MyCollection myCollection = new MyCollection();
        
        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 list = new ArrayList();
        
        list.add(new SubClass(1));
        list.add(new SubClass(2));
        list.add(new SubClass(2));
        list.add(new SubClass(3));
        
        // 删除元素方式一: 循环删除num==2的元素
        for(Iterator 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 list = new ArrayList();
        
        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的原因吧。

你可能感兴趣的:(Java基础知识)