1

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?

Jiew Meng
  • 84,767
  • 185
  • 495
  • 805

6 Answers6

5

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.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
1

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

API

Russell Zahniser
  • 16,188
  • 39
  • 30
1

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);
marathon
  • 7,881
  • 17
  • 74
  • 137
0

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.

Community
  • 1
  • 1
Yuushi
  • 25,132
  • 7
  • 63
  • 81
  • You can put primitives in `ArrayLists`s? I thought you could only put objects, and at best wrappers for primitives. – blahman Jan 18 '12 at 04:25
  • @blahman The point was that primitive fields are fine when cloning, but object fields (like `ArrayList items`) are sources of trouble. – Ted Hopp Jan 18 '12 at 04:33
  • Oh...oops. Totally missed that. Sorry, Yuushi. My bad ^^' Also, thanks @TedHopp =) – blahman Jan 18 '12 at 04:38
0

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.

Community
  • 1
  • 1
blahman
  • 1,304
  • 1
  • 12
  • 18
0

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.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521