Andreas said:
The other question was, if there exists some method for deepCopying
an array of Cloneables.
I don't know of any standard method to do that. However, it's not so
hard to roll your own.
Here is one possible approach presented:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.Map;
public class ArraysCloning {
public static void main(String[] args) {
String[][] a0 = {{"a"}, {"b", "c"}};
String[][] a1 = a0.clone();
String[][] a2 = Arrays.copyOf(a0, a0.length);
String[][] a3 = deepClone(a0);
a0[1][1] = "c'";
System.out.println("a0=" + Arrays.deepToString(a0));
System.out.println("a1=" + Arrays.deepToString(a1));
System.out.println("a2=" + Arrays.deepToString(a2));
System.out.println("a3=" + Arrays.deepToString(a3));
}
public static <T> T[] deepClone(T[] a) {
return deepClone(a, new IdentityHashMap<Object, Object>());
}
@SuppressWarnings("unchecked")
private static <T> T deepClone(T a, Map<Object, Object> cloned) {
if (a == null) return null; // null clones to null
if (! a.getClass().isArray()) return a; // non-array clones to self
T c = (T) cloned.get(a);
if (c != null) return c; // already cloned clones to clone
// clone...
try {
c = (T) cloneMethod.invoke(a, (Object[])null);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getCause());
}
// remember clone
cloned.put(a, c);
// clone non-primitive array elements...
if (! c.getClass().getComponentType().isPrimitive()) {
Object[] ca = (Object[]) c;
for(int i = 0, len = ca.length; i < len; ++i) {
ca
= deepClone(ca, cloned);
}
}
return c;
}
private static final Method cloneMethod;
static {
try {
cloneMethod = Object.class
.getDeclaredMethod("clone", (Class<?>[])null);
cloneMethod.setAccessible(true);
} catch (Exception e) {
throw new Error(e);
}
}
}
Which prints out the following:
a0=[[a], [b, c']]
a1=[[a], [b, c']]
a2=[[a], [b, c']]
a3=[[a], [b, c]]
(To make an example shorter it utilizes reflective clone() invocation
for each array type -- primitive and reference arrays. When maximum
speed (and safety) is needed it may be reimplemented to directly call
clone() depending on a component type of array being cloned -- just a
bit more of "ugly coding" needed...)
piotr