Question

I got the unchecked expression error when compiling and found the offending line to be

ArrayList<Integer> items = (ArrayList<Integer>) this.items.clone();

I am trying to perform a deep copy of my object so I am cloning a property of the object and array list in the above manner. How can I fix this warning?

  • I could use @SuppressWarnings("unchecked") but that is just hiding the problem (tho I expect none)
  • If I clone manually by looping through all elements to it will be slower I think

Whats the correct way of doing this?

Was it helpful?

Solution

If your elements are Integers, performing a "deep copy" really isn't an issue, since there's no reason why you would need to copy an Integer object. Just use new ArrayList<Integer>(this.items).

But for reference, neither clone() nor the ArrayList copy constructor will do a deep copy. It's only because your element types don't need deep copying that this satisfies your needs.

OTHER TIPS

You can get the same behavior with new ArrayList<Integer>(this.items). Either way, though, it's a shallow copy.

API

Integers are immutable, so it doesn't matter if you make a deep copy or not.

use the Collections utility class in java.util:

import java.util.Collections;
...
ArrayList<Integer> items = new ArrayList<Integer>(this.items.size());
Collections.copy(items, this.items);

Because of the backwards compatibility required when they introduced generics to the Java API, there's no way around using casting and @SuppressWarnings("unchecked") in some situations.

Also, see here for a reason why clone() usage should be used with care: it does a shallow copy, which is fine for primatives, but is dangerous with objects.

You've said you're trying to do a deep copy, but as discussed here, I doubt you'll be able to do that using clone(). So, like the other posters have said, it is a somewhat more hazardous method to use clone() and you won't be able to get the deep copy you've been looking for.

As others have pointed out, cloning the ArrayList does not clone its elements. If you want to make a deep copy of the contents, there's a neat trick: serialize and deserialize the array. (This works because ArrayList and Integer both implement Serializable.) However, this doesn't get rid of the need to suppress unchecked conversion warnings.

// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(this.items);
byte[] bytes = bos.toByteArray();

// Retrieve an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
    new ByteArrayInputStream(bytes));
ArrayList<Integer> items = (ArrayList<Integer>) in.readObject();

If your entire object can be declared Serializable, you could use this instead of a clone operation to make your deep copy. Also, see this article for a way to avoid the expense of copying the bytes out of the ByteArrayOutputStream.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top