I want to copy a list in Java, and I found a method called clone
, which does that, and it works fine, but I think I'm not using it correctly, as I get a warning in Eclipse .
What I do is create a list, add an integer to it, and finally use the copy method.
ArrayList<Integer> lista = new ArrayList<Integer>();
list.add(5);
ArrayList<Integer> listaCopiada = (ArrayList<Integer>) lista.clone();
Apparently there was a problem, the method returns a Object
, so I had to cast it, and when I do this, it works for me, but I get a warning.
Type safety: Unchecked cast from Object to ArrayList<Integer>
I can click on the warning and see multiple solutions, but none of them convince me.
Extract to local variable:
This duplicates the line, and then I get another warning of the same type.
ArrayList<Integer> clone = (ArrayList<Integer>) lista.clone();
ArrayList<Integer> clone2 = clone;
ArrayList<Integer> clone1 = clone2;
ArrayList<Integer> clone21 = clone1;
ArrayList<Integer> clone11 = clone21;
Extract to method:
This makes me a private function, which has a line inside with the same warning.
ArrayList<Integer> listaCopiada = extracted(lista);
private static ArrayList<Integer> extracted(ArrayList<Integer> lista) {
return (ArrayList<Integer>) lista.clone();
}
When I try to fix that warning, I'm left with a recursive function, which seems pretty illogical to me since it removes the clone part.
private static ArrayList<Integer> extracted1(ArrayList<Integer> lista) {
return extracted1(lista);
}
Add parentheses around cast:
This adds some meaningless parentheses for me, and the warning follows.
ArrayList<Integer> listaCopiada = ((ArrayList<Integer>) lista.clone());
The suggestion I get is Remove extra parentheses , this is going back to how it was before.
Add SuppressWarnings 'unchecked':
This forces me to use a comment to the code, telling me not to throw the warning. This is the only way that I don't get the warning anymore, but I think it looks ugly.
@SuppressWarnings("unchecked")
Is there a way (if it's possible the official or correct one) to use clone
without warnings like this?
About the warning, the only way to remove it is by using the
@SupressWarnings
. This happens because you are casting to a generic type. In Java, there is no other way to cast down to a generically defined object (in this case, fromObject
aArrayList<Integer>
) and remove the warning. There's nothing wrong with using@SupressWarnings
, as long as you know what you're doing. In case you removed the generic, you would get another warning about the use of raw variables (raw type), and you would still have to add this annotation.The method
clone
is a poor Java attempt to implement the prototype pattern . I say poor because technically it doesn't offer much value and it's just a shallow copy. There are only a few cases where the clone method should be called, such as on an array.For your case, if you only want a shallow copy with a new list with the same objects, that is, if you modify the state of one of the objects in the new list, you will also see the state change in the original list (because they are the same object), then the following is sufficient:
If you're looking for a deep copy, meaning that even the objects in the new list are different from the original and each hold their own state, you'll need to make sure that each element within your original list is either immutable or implements your own deep clone method like copy constructor, serialize/deserialize or other.
I would avoid using the
clone
. If you want to copy the list, you can simply do it like this:There are no ways to remove the warning other than disabling that type of message.
clone
it will return an element of typeObject
and that is something that you will not be able to modify.The alternative is to stop using
clone
and make a copy of the object using the copy constructor:You can use the class
java.util.Collections
:or the most common method: