[Ideas de programación Java comprensión de lectura] profunda y copia copia superficial

Profundo y copia copia superficial

Uno: para explicar lo

La llamada copia, como su nombre indica es copiar las propiedades de un objeto de replicar a otro objeto, pero en Java, la copia no es tan simple como en el sentido literal, se divide en copia de copia de copia profunda y superficial en Java. En un principio, en primer lugar definir lo que se llama un clon del objeto de destino original, el objeto después del clon llamado el nuevo objeto a un objeto definido otros objetos, y así sucesivamente, lo llamaremos la cadena de objetos

  • copia superficial : Después de copia superficial es copiar los valores de los tipos primitivos y los tipos de referencia para esta dirección será copiado a un nuevo tipo de referencia del objeto, por lo copia en profundidad, la referencia al tipo de cambios en el objeto original, el nuevo objeto tendrá influencia, y viceversa.

  • copia profunda : copia profunda del objeto es a todas las propiedades, así como objetos de objetos se copian en un nuevo objeto se clona, el tipo básico del objeto original, y luego directamente al valor de los tipos básicos de copia el nuevo objetivo para los tipos de referencia de objetos originales, que es para todos los miembros de los tipos de referencias se abren totalmente copia de espacio en la memoria, en lugar de simplemente copiar una referencia, si hay otros objetos en el objeto, que es una referencia a un objeto en la cadena todos los objetos se repliquen completamente. Por lo tanto, después de la copia profunda terminado, el objeto original en el nuevo objeto y el objeto original es completamente dos objetos diferentes, todas las direcciones no son los mismos, por lo que para cualquier cambio en el objeto original, no tendrá ningún efecto sobre el nuevo objeto, y viceversa Sin embargo.

    En pocas palabras, una copia profunda de referencia variable miembro de datos de la cadena de objeto de tipo todos los objetos se abrieron espacio de memoria; y poco profunda copia solo punto a la dirección de entrega, el nuevo objeto no crea espacio de memoria de tipos de datos de referencia.

En segundo lugar, comprender dibujo

copia superficial: copia superficial tipo de dirección visible de una referencia al nuevo objeto es simplemente directamente a la referencia de objeto original correspondiente al tipo de la fig. Así que no importa que cambió a otro objeto obj obj influirá

copia profunda: una copia profunda se ve desde la Fig cada objeto es totalmente replicada, y sus direcciones son diferentes, por lo que cambios en el objeto original o un nuevo objeto no afectarán entre sí

En tercer lugar, la puesta en práctica

3.1. Aplicación copia superficial

3.1.1 constructor de copia

Dado que la asignación del objeto Java, una referencia es similar a la copia original del objeto a otro objeto, el método realmente utilizado también puede estar configurado para lograr una copia superficial

/**
 * 通过构造方法进行浅拷贝
 */
@Data
class Dog implements Cloneable{

    private String name;
    private  int age;
    private Foot foot;

    public Dog(Dog dog){
        this.age=dog.age;
        this.name=dog.name;
        this.foot=dog.foot;
    }
    public Dog(String name, int age,Foot foot){
        this.age=age;
        this.name=name;
        this.foot=foot;
    }
    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +",address="+System.identityHashCode(this)+
                ", foot=" + foot +
                '}';
    }
}
@Data
class Foot {
    private String footNum;
    public Foot(String footNum) {
        this.footNum = footNum;
    }

    @Override
    public String toString() {
        return "Foot{" +
                "footNum=" +footNum +",address="+System.identityHashCode(this) +","+
                '}';
    }
}
public class ShallowCopy {
    public static void main(String[] args) {
        Foot foot = new Foot("四只脚");
        Dog dog1 = new Dog("旺财", 12, foot);
        Dog dog2 = new Dog(dog1);
        System.out.println("原对象---"+dog1);
        System.out.println("克隆后---"+dog2);
        dog1.setAge(18);
        foot.setFootNum("六只脚");
        System.out.println("修改后的原对象---"+dog1);
        System.out.println("修改后克隆对象---"+dog2);

    }

}

salida:

原对象---Dog{name='旺财', age=12,address=1406718218, foot=Foot{footNum=四只脚,address=245257410,}}
克隆后---Dog{name='旺财', age=12,address=1705736037, foot=Foot{footNum=四只脚,address=245257410,}}
修改后的原对象---Dog{name='旺财', age=18,address=1406718218, foot=Foot{footNum=六只脚,address=245257410,}}
修改后克隆对象---Dog{name='旺财', age=12,address=1705736037, foot=Foot{footNum=六只脚,address=245257410,}}

Podemos ver el valor de la dirección y dog1 DOG2 los pies del objeto son los mismos, y tienen un impacto en los cambios dog1 en el pie se DOG2

3.1.2. Método clon de reescritura

Mediante la implementación de la interfaz Cloneable y reemplazar el método clon de la clase de objeto de conseguir una copia superficial, a destacar aquí es que se quiere lograr una copia superficial por el método de clon, es necesario implementar la interfaz Cloneable, de lo contrario se producirá una excepción CloneNotSupportedException. Venga a hablar acerca de la interfaz Cloneable, después de lo cual punto se puede encontrar que el código es el siguiente

public interface Cloneable {
}

Sí, dentro de nada Cloneable, Cloneable realmente se juega el papel de sólo un logotipo, su papel se utiliza para identificar una clase que puede ser clonado, si no implementar esta interfaz, en nombre de la clase no admite la clonación. Mirando hacia atrás cómo copia superficial de un método de clonación. Para facilitar el uso en el presente documento Pie Pie anteriormente código es

/**
 * 通过clone方法进行浅拷贝
 */
@Data
class Pig implements Cloneable{

    private String name;
    private  int age;
    private Foot foot;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Pig{" +
                "name='" + name + '\'' +
                ", age=" + age +",address="+System.identityHashCode(this)+
                ", foot=" + foot +
                '}';
    }
}
public class ShallowCopyClone {
    public static void main(String[] args) throws CloneNotSupportedException {
        Foot foot = new Foot("四只脚");
        Pig pig = new Pig();
        pig.setAge(18);
        pig.setFoot(foot);
        pig.setName("猪八戒");
        Pig clonePig = (Pig) pig.clone();
        System.out.println("原对象--"+pig);
        System.out.println("克隆后--"+clonePig);
        //现在改变pig中的属性
        pig.setAge(20);
        clonePig.setAge(80);
        pig.getFoot().setFootNum("一百只脚");
        System.out.println("修改后的原对象---"+pig);
        System.out.println("修改后克隆对象---"+clonePig);

    }
}

salida:

原对象--Pig{name='猪八戒', age=18,address=1406718218, foot=Foot{footNum=四只脚,address=245257410,}}
克隆后--Pig{name='猪八戒', age=18,address=1705736037, foot=Foot{footNum=四只脚,address=245257410,}}
修改后的原对象---Pig{name='猪八戒', age=20,address=1406718218, foot=Foot{footNum=一百只脚,address=245257410,}}
修改后克隆对象---Pig{name='猪八戒', age=80,address=1705736037, foot=Foot{footNum=一百只脚,address=245257410,}}

Puede ser visto desde la salida, y como resultado de lo anterior, la dirección de código hash del pie son los mismos, y se refieren a otros objetos en el objeto cambia clon afectará a las propiedades de cualquier objeto

3.2. Aplicación copia profunda

3.2.1 reescribir todo clon

La idea es el objeto para cada cadena de objetos se clonan, y el clon llamar a todos los métodos de clonación de clase más alta, la conclusión es, los objetos en la cadena de una copia superficial de cada objeto = copia profunda. la implementación del código:

/**
 * 通过重写所有的clone方法进行深拷贝
 */
@Data
class Ear implements Cloneable,Serializable{

    private int earNum;
    private String earName;

    @Override
    public String toString() {
        return "Ear{" +
                "earNum=" + earNum +
                ", earName='" + earName + '\'' +",address="+System.identityHashCode(this)+
                '}';
    }
    public Ear(int earNum, String earName) {
        this.earNum = earNum;
        this.earName = earName;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
@Data
class Cat implements Cloneable, Serializable {
    private  int age;
    private String name;
    private Ear ear;
    
    public Cat(int age, String name, Ear ear) {
        this.age = age;
        this.name = name;
        this.ear = ear;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Cat cloneCat =(Cat) super.clone();
        //对Ear进行克隆
        cloneCat.ear = (Ear) cloneCat.getEar().clone();
        return cloneCat;
    }
    @Override
    public String toString() {
        return "Cat{" +
                "age=" + age +
                ", name='" + name + '\'' +",address="+System.identityHashCode(this)+
                ", ear=" + ear +
                '}';
    }
}
public class DepthCopy {
    public static void main(String[] args) throws CloneNotSupportedException {
        Ear ear = new Ear(2, "左耳朵");
        Cat cat = new Cat(18, "加菲猫", ear);
        Cat cloneCat = (Cat)cat.clone();
        System.out.println("原始的"+cat);
        System.out.println("克隆的"+cloneCat);
        //和之前一样改变ear的值
        ear.setEarName("右耳朵");
        ear.setEarNum(1);
        System.out.println("修改后的原对象"+cat);
        System.out.println("修改后克隆对象"+cloneCat);
    }
}

salida:

原始的Cat{age=18, name='加菲猫',address=1406718218, ear=Ear{earNum=2, earName='左耳朵',address=245257410}}
克隆的Cat{age=18, name='加菲猫',address=1705736037, ear=Ear{earNum=2, earName='左耳朵',address=455659002}}
修改后的原对象Cat{age=18, name='加菲猫',address=1406718218, ear=Ear{earNum=1, earName='右耳朵',address=245257410}}
修改后克隆对象Cat{age=18, name='加菲猫',address=1705736037, ear=Ear{earNum=2, earName='左耳朵',address=455659002}}

Como puede verse por la salida, después de una copia en profundidad, dirección valores de objeto de oreja de gato es diferentes objetos, dos objetos se pueden indicar que este no está relacionado, y por lo tanto cambiar cualquier objeto gato, no va a ser de impacto clon.

Sin embargo, utilizando este enfoque de la copia en profundidad también tiene una desventaja obvia, si un objeto se hace referencia a sólo una o dos objetos, mejor dicho, sólo tiene que reemplazar el método clon en estos objetos se puede realizar copia profunda, pero si un objeto no se puede modificar cuando muchos objetos se refieren a objetos, y las referencias a objetos y referencias a otros objetos, o referencias, la siguiente cadena de destino es muy larga, la cadena debe estar sujeto a reescribir el método clon se convierte en demasiado problema . Este tiempo generalmente puede seleccionar mediante una secuencia de copia profunda.

3.2.2. Serialización

Déjame hablar primero sobre lo que está serializado en el final, la siguiente es una explicación de Baidu de la secuencia de

Serialización: serialize (la serialización) se convierte en información de estado del objeto puede ser almacenada o transmitida en forma de proceso. Durante la serialización, el estado actual del objeto que debe escribirse en un área de almacenamiento temporal o permanente. Más tarde, leyendo o deserializar un objeto desde un área de almacenamiento en un estado, vuelva a crear el objeto;

Mi propia opinión es que el objeto es visto como una casa grande, y la serialización es poner esta casa en todas las estructuras, incluyendo cada tabla (referencia de objeto) cómo poner qué hacer con el material, se utilizan dibujo grabado. A continuación, la casa será eliminado pieza a pieza, que se transportan en camiones a donde se necesita, y luego tomar hasta (deserializar) por sorteo. Para los objetos de Java, copias entonces se serializa el valor de todos los objetos en el objeto, por ejemplo una edad objetivo es 12, entonces se pondrá a la información leída después de deserialización, creación de objetos. Por lo que podemos conseguir una copia profunda de esta manera.

la implementación del código

/**
 * 通过序列化进行深拷贝
 */
public class DepthCopySerializable{
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        Ear ear = new Ear(2, "左耳");
        Cat cat = new Cat(15, "加菲猫", ear);
        ByteArrayOutputStream BO = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = new ObjectOutputStream(BO);
        outputStream.writeObject(cat);
        outputStream.flush();
        ObjectInputStream inputStream=new ObjectInputStream(new ByteArrayInputStream(BO.toByteArray()));
        Cat cloneCat = (Cat) inputStream.readObject();
        System.out.println("原始的"+cat);
        System.out.println("克隆后"+cloneCat);
        //改变ear
        ear.setEarNum(6);
        ear.setEarName("右耳朵");
        System.out.println("改变ear后的原对象-----"+cat);
        System.out.println("改变ear后克隆对象-----"+cloneCat);


    }
}

exportación

原始的Cat{age=15, name='加菲猫',address=295530567, ear=Ear{earNum=2, earName='左耳',address=2003749087}}
克隆后Cat{age=15, name='加菲猫',address=193064360, ear=Ear{earNum=2, earName='左耳',address=109961541}}
改变ear后的原对象-----Cat{age=15, name='加菲猫',address=295530567, ear=Ear{earNum=6, earName='右耳朵',address=2003749087}}
改变ear后克隆对象-----Cat{age=15, name='加菲猫',address=193064360, ear=Ear{earNum=2, earName='左耳',address=109961541}}

Y la copia en profundidad por encima de la misma secuencia de dirección después de lograrse mediante copia profunda es diferente, lo que indica que estos son dos objetos completamente diferentes. La naturaleza no se verá afectada

Supongo que te gusta

Origin www.cnblogs.com/blackmlik/p/12515952.html
Recomendado
Clasificación