1

From this SO-question, answers and comments I know that the result of

ArrayList<Object> listClone = new ArrayList<Object>(list);

does an extra step behind the scenes in comparison to

@SuppressWarnings("unchecked")
ArrayList<Object> listClone = (ArrayList<Object>)list.clone();

but the results are the same. So why is there even a Copy Constructor when we have a Clone Method?

NOTE: This question is mostly directed to the ArrayList, since I know that it has both a Copy Constructor and a Clone Method. If there are any Java Objects that has either of them, but not both, then I wasn't aware of that. Still, my question is directed to the case of ArrayList.

So, what is the purpose of it? In which case would you prefer to use the ArrayList's Copy Constructor instead of its Clone Method?

PS: If anyone has the exact code of both the Copy Constructor and the Clone Method of the Java#ArrayList for comparison, that would be great.

Community
  • 1
  • 1
Kevin Cruijssen
  • 9,153
  • 9
  • 61
  • 135

3 Answers3

3

So, what is the purpose of it?

Look at the signature of the copy constructor:

   ArrayList(Collection<? extends E> c)

It constructs a list from any collection; e.g. a LinkedList, any kind of Set, etcetera.

By contrast, you can only clone() an ArrayList from another ArrayList.

Now there are undoubtedly "issues" with clone() in general. However for (at least) the standard non-concurrent collection classes, cloning works just as well as the copy constructor ... modulo that it does the job; see above. For these classes, the clone() method is defined to return a shallow copy; see the respective class javadocs.


If anyone has the exact code of both the Copy Constructor and the Clone Method of the Java#ArrayList for comparison, that would be great.

Google is your friend. Google for "java.util.ArrayList" source.

(I prefer the Grepcode site. It has multiple versions of the code, and a nice UI for navigating the code, the package hierarchy, the class hierarchy, and even definition / usage relationships.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    Note, of course, that the source needn't be canonical. Anyone can implement the standard libraries, so long as they do the right things. That means that there's not necessarily any "exact code of both the Copy Constructor and the Clone Method". – Joshua Taylor Jul 31 '14 at 12:30
  • @JoshuaTaylor - Good point. Indeed, GrepCode has a number of different versions of `java.util.ArrayList` ranging from Java 6 to Java 8. – Stephen C Jul 31 '14 at 12:32
1

There is a small difference that I know of. The copy constructor takes a Collection, not only an Arraylist. It is more of a "fill all that stuff into the new ArrayList"-constructor, than a copy constructor. Also the order of the elements is determined by the iterator of the given collection.

The .clone() method on the other hand creates a new ArrayList out of the given ArrayList.

One situation where these two work differently:

List a=new ArrayList();
List l=new LinkedList();

List a2 = new ArrayList(a); //returns ArrayList
List a3 = new ArrayList(l); //returns ArrayList
List a4 = a.clone();        //returns ArrayList
List a5 = l.clone();        //returns LinkedList
Dakkaron
  • 5,930
  • 2
  • 36
  • 51
1

As I understand, it is much up to your design intentions which one you would use, but the clone() method is generally considered to be broken. This may be a good reason designers add a proper copy constructor.

Here are some pros and cons:

  • The clone() method is considered to rise problems. For one thing, by default it is not clear if a deep or a shallow copy is meant. If you call super.clone() up the hierarchy, you may end up having a shallow copy of a mutable object, which was not your intention.
  • Some people use clone() for arrays only, as there it is faster.
  • Cloneable is unclear. If something is Cloneable, it may still be very unclear what you really can do with, as it has no public clone() method and neither has Object.
  • The copy constructor has the advantage of handling generics (as Stephen C shows).

Here are some interesting sources to read:


Then, you've asked for source code of ArrayList copy constructor and clone:

ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
 }


public Object clone() {
    try {
        @SuppressWarnings("unchecked")
         ArrayList<E> v = (ArrayList<E>) super.clone();
         v.elementData = Arrays.copyOf(elementData, size);
         v.modCount = 0;
         return v;
     } catch (CloneNotSupportedException e) {
         // this shouldn't happen, since we are Cloneable
         throw new InternalError();
     }
 }

Got this from CodeGrep.

Community
  • 1
  • 1
peter_the_oak
  • 3,529
  • 3
  • 23
  • 37