Explicación detallada de la clonación de objetos Java

Descripción general: cuando creamos un objeto, las propiedades en él se inicializarán y el método de clonación se usa para guardar el valor inicializado. Por lo general, lo más común que vemos es que una referencia a un objeto apunta a otro objeto, no a dos. se crean objetos.

 Person p1 = new Person(100,"jim");
        Person p2 = p1;

        System.out.println(p1==p2);//true

La clonación definitivamente crea dos objetos.

 Person p1 = new Person(100,"jim");
        Person p2 =p1.clone();//克隆的新对象

        System.out.println(p1==p2);//false

La clonación se divide en clonación superficial (ShallowClone) y clonación profunda (DeepClone).

En el lenguaje Java, los tipos de datos se dividen en tipos de valor (tipos de datos básicos) y tipos de referencia. Los tipos de valor incluyen tipos de datos simples como int, double, byte, boolean y char, y los tipos de referencia incluyen tipos complejos como clases, interfaces y arreglos. El valor del tipo básico se puede copiar directamente y el tipo de referencia solo puede copiar la dirección de referencia. Entonces, la principal diferencia entre la clonación superficial y la clonación profunda es si admite la duplicación de variables miembro de tipos de referencia.

sistema.

clon superficial

En la clonación superficial, si la variable miembro del objeto prototipo es un tipo de valor, se realizará una copia en el objeto clonado; si la variable miembro del objeto prototipo es un tipo de referencia, la dirección del objeto de referencia se copiará en el objeto clonado, es decir, el prototipo Las variables miembro del objeto y del objeto clonado apuntan a la misma dirección de memoria. En pocas palabras, en la clonación superficial, cuando se copia el objeto, solo se copian él mismo y las variables miembro del tipo de valor que contiene, mientras que los objetos miembro del tipo de referencia no se copian.

Método para realizar:

1. En el lenguaje Java, la clonación superficial se puede lograr anulando el método clone() de la clase Object.

2. Proporcione BeanUtils.copyProperties (fuente, destino) en el marco de primavera;

Aquí demostramos principalmente la implementación reescribiendo el método de clonación en el objeto

1. Primero defina una clase (la clase que necesita ser clonada)

public class Person implements  Cloneable{

     int num;
     String name;
     Address address;

    public Person() {
    }

    public Person(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person)super.clone();
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

2. Puede ver que la clase Persona está asociada con la clase Dirección y escribirla

public class Address  {

     String  address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}

3. Escriba una clase de prueba para probar

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address();
                address.setAddress("汉中");

        Person p1 = new  Person(100,"jim");
               p1.setAddress(address);

        Person p2 =p1.clone();
               p2.setName("tom");
               address.setAddress("西安");

        System.out.println(p1); // jim   西安
        System.out.println(p2);// tom    西安
    }
}

Primero mire el atributo de nombre, el nombre de p1 es jim, otro objeto p2 se clona y el nombre se cambia a tom, porque hay dos objetos, por lo que los resultados de salida son diferentes.

Mirando de nuevo los objetos asociados, la dirección con información de Hanzhong se agrega primero a p1, por lo que la dirección actual en p1 es Hanzhong. Después de clonar p2, de hecho, solo se clona la dirección para la dirección, por lo que p1 y p2 apuntan a ambos. es la misma dirección, por lo que todos son Hanzhong y, después de otra revisión, todos son Xi'an.

Entonces, la clonación superficial solo clona la dirección de la variable de tipo de referencia.

clon profundo

En la clonación profunda, sin importar si la variable miembro del objeto prototipo es un tipo de valor o un tipo de referencia, se realizará una copia en el objeto clonado y la clonación profunda también copiará una copia de todos los objetos de referencia del objeto prototipo en el objeto clonado. En pocas palabras, en la clonación profunda, además de copiar el objeto en sí, también se copiarán todas las variables miembro contenidas en el objeto.

En el lenguaje Java, si necesita implementar una clonación profunda, puede implementarla anulando el método clone() de la clase Object , o puede implementarla a través de la serialización (Serialización) y otros métodos . La serialización es el proceso de escribir un objeto en un flujo. El objeto escrito en el flujo es una copia del objeto original, y el objeto original todavía existe en la memoria. La copia lograda a través de la serialización no solo puede copiar el objeto en sí, sino también los objetos miembros a los que se refiere. Por lo tanto, escribir el objeto en una secuencia a través de la serialización y leerlo desde la secuencia puede realizar una clonación profunda. Cabe señalar que la clase del objeto que puede realizar la serialización debe implementar la interfaz Serializable, de lo contrario, la operación de serialización no se puede realizar.

1. Anule el método de clonación en la clase Object

1. Primero defina una clase (la clase que debe clonarse) y agregue una línea de código para clonar el objeto de dirección en comparación con el clon superficial anterior

public class Person implements  Cloneable{

     int num;
     String name;
     Address address;

    public Person() {
    }

    public Person(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person)super.clone();
        person.address = (Address)address.clone();   //深度复制  联同person中关联的对象也一同克隆.
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

2. La dirección está escrita, en comparación con el clon superficial anterior, hay un método de clonación más que reescribe la clase de Objeto

public class Address  {

     String  address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }

   @Override
    protected Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }
}

3. Clase de prueba de prueba fija

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address();
                address.setAddress("汉中");

        Person p1 = new  Person(100,"jim");
               p1.setAddress(address);

        Person p2 =p1.clone();
               p2.setName("tom");
               address.setAddress("西安");

        System.out.println(p1); // jim   西安
        System.out.println(p2);// tom    汉中
    }
}

El resultado será diferente esta vez, porque el clon profundo no solo se clona a sí mismo, sino que también clona los objetos de las clases asociadas, por lo que el Hanzhong original almacenado en p1 se clona en p2, y la última línea cambiada a Xi'an es The objeto de dirección original, la dirección original ha sido clonada y guardada en p2

2. Modo de serialización (Serialización)

Si hay demasiados objetos de otras clases asociados en la clase que necesita clonarse, tomará mucho tiempo clonar los objetos asociados uno por uno si continúa usando la clonación profunda, y el método de serialización puede hacer que todos los asociados objetos en la clase Conviértalo en un flujo y clonelo en colegios y universidades.

1. O crea un objeto asociado con la clase clonada

public class Address  implements Serializable {

     String  address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }

}

2. Clase de persona, que escribe un método de clonación de su propio método de serialización.

public class Person implements Serializable {

     int num;
     String name;
     Address address;

    public Person() {
    }

    public Person(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    /**
     * 自定义克隆方法
     * @return
     */
    public Person myclone() {
            Person person = null;
              try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
                     ByteArrayOutputStream baos = new ByteArrayOutputStream();
                      ObjectOutputStream oos = new ObjectOutputStream(baos);
                      oos.writeObject(this);
            // 将流序列化成对象
                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                     ObjectInputStream ois = new ObjectInputStream(bais);
                     person = (Person) ois.readObject();
                  } catch (IOException e) {
                     e.printStackTrace();
                  } catch (ClassNotFoundException e) {
                     e.printStackTrace();
                 }
             return person;
          }


    @Override
    public String toString() {
        return "Person{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

3. Prueba de clase de prueba

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address();
                address.setAddress("汉中");

        Person p1 = new  Person(100,"jim");
        p1.setAddress(address);

        Person p2 =p1.myclone();
               p2.setName("tom");
               address.setAddress("西安");

        System.out.println(p1);jim   西安
        System.out.println(p2);tom   汉中
    }
}

Por lo tanto, depende de la situación específica para elegir

Supongo que te gusta

Origin blog.csdn.net/weixin_71243923/article/details/128959956
Recomendado
Clasificación