static Object clone(Object o) { return clone(o, new IdentityHashMap); } static Object clone(Object o, IdentityHashMap seen) ctex { if (o == null) return o; Object y = seen.get(o); if (y != null) return y; if (o instanceof List) { print("Cloning list: " + o); List l = new ArrayList(); seen.put(o, l); for (Object x : (List) o) l.add(clone(x, seen)); return l; } if (o instanceof Map) { Map m = o instanceof TreeMap ? new TreeMap() : new HashMap(); seen.put(o, m); for (O entry : ((Map) o).entrySet()) { Map.Entry e = (Map.Entry) entry; m.put(clone(e.getKey(), seen), clone(e.getValue(), seen)); } return m; } if (o instanceof String || o instanceof Number || o instanceof Boolean) return o; if (o instanceof Object[]) { Object[] l = (Object[]) o; Object[] l2 = l.clone(); seen.put(o, l2); for (int i = 0; i < l.length; i++) l2[i] = clone(l[i], seen); return l2; } // clone an arbitrary custom object // TODO: use Constructor object and setAccessible print("Cloning custom: " + o); Object clone = o.getClass().newInstance(); seen.put(o, clone); Class c = o.getClass(); while (c != Object.class) { Field[] fields = c.getDeclaredFields(); for (Field field : fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; Object value; field.setAccessible(true); value = field.get(o); field.set(clone, clone(value, seen)); } c = c.getSuperclass(); } return clone; }