Java Clone explicado: Evita errores al duplicar objetos

| Última modificación: 8 de octubre de 2024 | Tiempo de Lectura: 3 minutos

Algunos de nuestros reconocimientos:

Premios KeepCoding

Lo más probable es que, si trabajas con Java, debas enfrentarte a la tediosa tarea de clonar objetos. Ya sea porque necesitas duplicar datos, evitar modificar el original o simplemente porque quieres copiar estructuras más complejas, la operación de clonación es algo que aparece con frecuencia. Te mostraremos como hacer este proceso con Java Clone, una herramienta que te salvara de cometer errores comunes al duplicar objetos.

que es java clone

¿Qué es Java Clone y cómo funciona?

Con Java Clone puedes crear una copia exacta de un objeto. Para usarlo simplemente tienes que implementar el interfaz Cloneable y sobrescribir el método clone(). Este método es el responsable de realizar la clonación del objeto, creando una nueva instancia con los mismos valores que el objeto original.

Imagina que tienes una clase Factura y quieres clonar sus instancias.

public class Factura implements Cloneable {
private int numero;
private String concepto;
private double importe;

public Factura(int numero, String concepto, double importe) {
this.numero = numero;
this.concepto = concepto;
this.importe = importe;
}

@Override
protected Object clone() throws CloneNotSupportedException {
return new Factura(this.numero, this.concepto, this.importe);
}
}

Lo que hicimos fue implementar Cloneable y sobrescribir el método clone(), de tal manera que creamos una copia de la instancia de Factura. El método clone() devuelve una nueva instancia de Factura con los mismos valores de número, concepto e importe que el original.

Cómo usar Java Clone en un programa

Con este ejemplo vas a aprender a usar la clase clonable en el programa principal. Por ejemplo, si tienes una instancia de Factura que quieras duplicar, haz lo siguiente:

public class Principal {
public static void main(String[] args) {
Factura f = new Factura(1, "ordenador", 500);
try {
Factura nueva = (Factura) f.clone();
nueva.setNumero(2); // Cambiamos el número de la nueva factura

System.out.println(f.getNumero()); // Salida: 1
System.out.println(f.getConcepto()); // Salida: ordenador
System.out.println(f.getImporte()); // Salida: 500

System.out.println("****************");

System.out.println(nueva.getNumero()); // Salida: 2
System.out.println(nueva.getConcepto());// Salida: ordenador
System.out.println(nueva.getImporte()); // Salida: 500
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

Como ves se creó una nueva factura clonando la original, pero se cambió el número de la nueva factura y se imprimieron ambos objetos para ver los resultados. Esto demuestra que la clonación ha funcionado correctamente, creando una copia independiente de la factura original.

Problemas comunes con Java Clone

Una limitación que tiene Java Clone, es que realiza una clonación superficial. Esto quiere decir que solo copia las referencias de los objetos internos, no sus valores. De tal manera que surgen problemas si tu clase tiene objetos anidados, como listas o mapas.

Por ejemplo, si tu clase Factura tiene una lista de LineaFactura:

public class Factura implements Cloneable {
private List<LineaFactura> lineas = new ArrayList<>();

@Override
protected Object clone() throws CloneNotSupportedException {
Factura nueva = (Factura) super.clone();
nueva.lineas = new ArrayList<>(this.lineas); // Clonamos también la lista
return nueva;
}
}

En este caso, necesitas asegurarte de clonar también los objetos anidados para evitar problemas con referencias compartidas. Si no lo haces, tanto el objeto original como el clonado compartirán la misma lista de LineaFactura, lo que puede generar errores si uno de ellos modifica la lista.

Java Deep Clone con Cloning

Si estas trabajando en escenarios más complejos, donde tienes objetos anidados o estructuras de datos grandes, puedes usar el deep cloning que copia no solo el objeto en sí, sino también todos los objetos a los que hace referencia.

Usa la librería Cloning cuando vayas a hacer deep cloning. De esta forma puedes clonar una Factura con una lista de LineaFactura usando esta librería:

import com.rits.cloning.Cloner;

public class Principal2 {
public static void main(String[] args) {
Factura f = new Factura(1, "ordenador", 500);
LineaFactura linea1 = new LineaFactura(1, 200, "cpu");
LineaFactura linea2 = new LineaFactura(2, 300, "monitor");

f.addLinea(linea1);
f.addLinea(linea2);

Cloner cloner = new Cloner();
Factura copia = cloner.deepClone(f);

// Imprimimos la copia para verificar que ha sido clonada completamente
System.out.println(copia.getNumero()); // Salida: 1
System.out.println(copia.getConcepto()); // Salida: ordenador
System.out.println(copia.getImporte()); // Salida: 500

for (LineaFactura lf : copia.getLineas()) {
System.out.println(lf.getNumero());
System.out.println(lf.getConcepto());
System.out.println(lf.getImporte());
}
}
}

Con esta librería podemos ver que sí se realizó una clonación profunda de Factura, porque se copiaron todas las líneas. Esto nos garantiza que el objeto original y el clon son completamente independientes, evitando los problemas de referencias compartidas.

Java Clone puede resultarte muy útil cuando necesites duplicar objectos, pero recuerda que puedes usar el deep cloning si vas a trabajar con estructuras mas complejas o listas de objetos.

Si este artículo ha despertado tu interés por aprender más sobre Java Clone y cómo crear aplicaciones robustas con este lenguaje, el Bootcamp de Java Full Stack de KeepCoding es perfecto para ti. Aprenderás a manejar tanto las bases de Java como las técnicas avanzadas de desarrollo, abriéndote paso a una carrera con alta demanda, grandes salarios y estabilidad laboral. ¡No pierdas la oportunidad de transformar tu vida profesional!

Ramón Maldonado

Full Stack Developer y Responsable de Formación base en KeepCoding.

Posts más leídos

¡CONVOCATORIA ABIERTA!

Java y Spring Boot

Full Stack Bootcamp

Clases en Directo | Profesores en Activo | Temario 100% actualizado