La copia profunda (copia profunda) y la copia superficial (copia superficial) son dos conceptos relativamente comunes, especialmente en el lenguaje C ++, si no lo comprende, tendrá problemas al eliminar, pero afortunadamente usamos Java aquí. Aunque Java gestiona automáticamente el reciclaje de objetos, todavía debemos prestar suficiente atención a la copia profunda (copia profunda) y la copia superficial (copia superficial), porque a veces estos dos conceptos suelen traernos mucha confusión.
Copia superficial significa que al copiar un objeto, solo se copia el objeto en sí (incluidas las variables básicas en el objeto), pero no se copia el objeto al que apunta la referencia contenida en el objeto. Una copia profunda no solo copia el objeto en sí, sino que también copia todos los objetos a los que apuntan las referencias contenidas en el objeto. Por ejemplo, para que quede más claro: el objeto A1 contiene una referencia a B1 y B1 contiene una referencia a C1. Copia superficial A1 para obtener A2. A2 todavía contiene una referencia a B1 y B1 todavía contiene una referencia a C1. La copia profunda es la recursión de la copia superficial. La copia profunda A1 para obtener A2 contiene una referencia a B2 (copia de B1) y B2 contiene una referencia a C2 (copia de C1).
Si el método clone () no se reescribe, el objeto obtenido al llamar a este método es una copia superficial. Centrémonos en la copia profunda a continuación.
Ejecute el siguiente programa para ver la copia superficial:
clase Profesor0 implementa Cloneable { nombre de cadena; int edad; profesor0 (nombre de cadena, int edad) { this.name = nombre; this.age = edad } public Object clone() lanza CloneNotSupportedException { return super.clone(); clase Student0 implementa Cloneable { Nombre de cadena; // Objeto constante. int age; Professor0 p;//Los valores de referencia del estudiante 1 y del estudiante 2 son los mismos. Estudiante0(nombre de cadena, int edad, Profesor0 p) { this.name = nombre; this.age = edad; this.p = p } public Object clone() { Student0 o = null; .clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString() } return o } } public class ShallowCopy { public static void; main(String[] args) { Profesor0 p = nuevo Profesor0("wangwu", 50); Estudiante0 s1 = nuevo Estudiante0("zhangsan", 18, p); Estudiante0 s2 = (Estudiante0) s1.clone(); p.nombre = "lisi"; s2.p.edad = 30; s2.nombre = "z"; s2.edad = 45; System.out.println("Nombre del estudiante s1:" + s1.name + "/n Nombre del profesor del estudiante s1:" + s1.p.name + "," + "/n Edad del profesor del estudiante s1" + s1 .p.age);//Profesor del alumno 1} }
s2 ha cambiado, pero s1 también ha cambiado, lo que demuestra que p de s1 y p de s2 apuntan al mismo objeto. Este no es el caso en nuestras necesidades reales, por lo que necesitamos una copia profunda:
clase Profesor implementa Cloneable { nombre de cadena; int edad; profesor (nombre de cadena, int edad) { this.name = nombre; this.age = edad } public Object clone() { Object o = null; clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); return o } } clase El estudiante implementa Cloneable { Nombre de cadena; int edad; Profesor p; Estudiante (nombre de cadena, int edad, Profesor p) { this.name = nombre; this.age = edad; this.p = p } clon de objeto público () { Estudiante o = nulo; o = (Estudiante) super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString() } op = (Profesor) p.clone(); return o; } } public class DeepCopy { public static void main(String args[]) { long t1 = System.currentTimeMillis(); Profesor p = nuevo Profesor("wangwu", 50); = nuevo Estudiante("zhangsan", 18, p); Estudiante s2 = (Estudiante) s1.clone(); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // El profesor del estudiante 1 no cambia. largo t2 = System.currentTimeMillis(); System.out.println(t2-t1);
Por supuesto, también tenemos un método de copia profunda, que consiste en serializar el objeto:
import java.io.*; // La serialización requiere mucho tiempo class Professor2 implements Serializable { /** * */ private static final long serialVersionUID = 1L; int age; nombre = nombre; this.age = edad; } } class Student2 implements Serializable { /** * */ private static final serialVersionUID = 1L; objeto constante. int age; Professor2 p;// Los valores de referencia del estudiante 1 y del estudiante 2 son los mismos. Student2(String name, int age, Professor2 p) { this.name = name; this.age = age; this.p = p } public Object deepClone() throws IOException, OptionalDataException, ClassNotFoundException { // Escribe el objeto en flujo en ByteArrayOutputStream bo = nuevo ByteArrayOutputStream(); ObjectOutputStream oo = nuevo ObjectOutputStream(bo); oo.writeObject(this); // Leer ByteArrayInputStream de la secuencia bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); /** * @param args */ public static void main(String[] args) lanza una excepción de datos opcional, IOException, ClassNotFoundException { long t1 = System.currentTimeMillis(); Profesor2 p = nuevo Profesor2("wangwu", 50); Estudiante2 s1 = nuevo Estudiante2("zhangsan", 18, p); (); s2.p.nombre = "lisi"; s2.p.edad = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // El profesor del estudiante 1 no cambia. largo t2 = System.currentTimeMillis(); System.out.println(t2-t1);
Sin embargo, la serialización lleva mucho tiempo. En algunos marcos, podemos sentir que a menudo serializan objetos y luego los transfieren, lo que lleva mucho tiempo.