发现实现Collection借口中addAll()方法存在一个微妙的陷阱

发现实现Collection借口中addAll()方法存在一个微妙的陷阱

转载
今天我在自己构建JDK中的ArrayList时发现了一个有趣的陷阱。现在把它陈述出来:
对于 boolean Collection.addAll(Collection c)方法,源码里面
有这样的说明:
<------------------------------------------------------------------->
  /**
     * Adds all of the elements in the specified collection to this set if
     * they're not already present  (optional operation).  If the specified
     * collection is also a set, the addAll operation effectively
     * modifies this set so that its value is the union of the two
     * sets.   The behavior of this operation is unspecified if the specified
     * collection is modified while the operation is in progress.
   *
   *........
   *........
<------------------------------------------------------------------->

对于第一句话有个补充说明(optional operation:非限制的操作),这就意味着有这
样一种情况可能发生:
    假如有一个类引用了Collection借口(就拿JDK中的ArrayList类来说吧),并没
有限制不能向里面添加已经存在了的元素。即:
以下操作合法:
     Collection c = new ArrayList();
     c.add("a");
     c.add("b");
     c.addAll(c);
以上的代码是合法的。而且结果是有两个a和两个b。

今天我自己在编写一个MyArrayList类时也引用Collection等借口。有意思的是在实
现addAll()方法时遇到了问题。
这个问题原来是个很微妙的陷阱。现在我把它列出来。

我自己写实现的boolean addAll(Collection c)方法如下,是有个
bug的。后来才发现(太隐秘了,开始还没发现)。

<------------------------------------------------------------------->
public class MyArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
        {
        
            private int size;
            //......
            
             public boolean addAll(Collection c) {
                 Object[] a = c. toArray();      //把c转化为数组

            ensureCapacity( size + c.size() );        //分配新的空间
            
            for(int i =0 ; i < elementData.length ; i++){        //逐个添加
                 add( a[ i ] );
            }
            } 
       
            //......
        
        }
<------------------------------------------------------------------->

这断代码看起来没有问题,运行起来好像也没有什么问题,就连有重复数据的两个
数组也可以相连。
但是这断代码有个严重的错误:如下:
        Collection c = new MyArrayList();
        c.add("a");
        c.add("b");
        c.addAll(c);

你可能感兴趣的:(发现实现Collection借口中addAll()方法存在一个微妙的陷阱)