Hay dos enfoques populares. Una es proporcionar un método clone
como usted mencionó, como tal.
public class C implements Cloneable {
@Override public C clone() {
try {
final C result = (C) super.clone();
// copy fields that need to be copied here!
return result;
} catch (final CloneNotSupportedException ex) {
throw new AssertionError();
}
}
Preste atención a los "campos de copia ... aquí!" parte. La inicial result
es solo una copia superficial, lo que significa que si hay una referencia a un objeto, tanto el original como result
compartirán el mismo objeto. Por ejemplo, si C
contiene private int[] data
, probablemente querrá copiar eso.
...
final C result = (C) super.clone();
result.data = data.clone();
return result;
...
Tenga en cuenta que no es necesario copiar los campos primitivos, ya que su contenido se ha copiado, o los objetos inmutables, ya que no pueden cambiar de todos modos.
El segundo enfoque es proporcionar un constructor de copia.
public class C {
public C(final C c) {
// initialize this with c
}
}
O una fábrica de copias.
public class C {
public static C newInstance(final C c) {
return new C(c);
}
private C(final C c) {
// initialize this with c
}
}
Ambos enfoques tienen sus respectivas propiedades. clone
es bueno porque es un método, por lo que no es necesario saber el tipo exacto. Al final, siempre debes terminar con una copia "perfecta". El constructor de copias es agradable porque la persona que llama tiene la oportunidad de decidir, como se puede ver en las Colecciones de Java.
final List c = ...
// Got c from somewhere else, could be anything.
// Maybe too slow for what we're trying to do?
final List myC = new ArrayList(c);
// myC is an ArrayList, with known properties
Recomiendo elegir cualquier enfoque, el que más le convenga.
Utilizaría los otros enfoques, como la copia reflectiva o la serialización/deserialización inmediata, solo en pruebas unitarias. Para mí, se sienten menos apropiados para el código de producción, principalmente por cuestiones de rendimiento.
¿Esto es para el propósito de prueba solamente (unidad de prueba), o ¿necesita esta funcionalidad en el código de producción real? – crunchdog