martes, enero 20, 2009

Otra forma de clonar objetos en Java

Como todos los programadores sabreis las variables en Java, a excepción de los tipos básicos, son referencias a objetos. Por ellos cuando asignamos una variable a otra no estamos duplicando el objeto sino que tendremos dos referencias al mismo objeto. En ocasiones podemos necesitar duplicar un objeto y para esto la API nos provee de la interfaz Cloneable. Cada objeto implicado en la clonación deberá implementar Cloneable e implementar el método clone(). Si es un objeto simple compuesto de tipos básicos esto es fácil pero imaginemos que después de seis meses de desarrollo necesitamos clonar un objetos que referencia de forma directa o indirecta a otros treinta objetos. Es una paliza ponerte a implementar Cloneable y además avisar al resto del proyecto que si crean un nuevo DTO que va a ser referenciado por uno de esos treinta objetos pues que el nuevo DTO también debe implementar Cloneable. Una solución rápida, sencilla y nada intrusiva es la que os propongo:


public Object deepCopy(){
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
// serialize and pass the object
oos.writeObject(this);
oos.flush();
ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bin);
// return the new object
return ois.readObject();
} catch (Exception ex) {
throw new RuntimeException("Error while making a deep copy of object: {0}", ex);
}
}

Desconozco cual puede ser el rendimiento de esta función en comparación al estándar. Por supuesto es necesario que las clases implicadas implementen Serializable y los atributos anotados como Transient no serán copiados.
¿Que opinión os merece? ¿le veis alguna pega más?

Actualizado (24/02/2009)
He hecho algunas pruebas de rendimiento, las podeis ver aquí.

2 comentarios:

  1. Interesnate mecanismo. Podrías escribirlo como artículo en debugmodeon :)

    ResponderEliminar
  2. Funciona perfecto. muxas gracias

    ResponderEliminar