Interpretação de cópia superficial e cópia profunda combinada com JVM

java.lang.CloneableEle também java.io.Serializablepertence à interface marcada e não define nenhum método e atributo.
Insira a descrição da imagem aqui

Uma classe deseja usar o método clone

  • 重写clone()方法, Porque o modificador de clone () de Object está protegido;
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
  • 实现Cloneable接口Caso contrário, CloneNotSupportedException será lançado.
    Insira a descrição da imagem aqui

Tipo de clone

  • 浅拷贝, Ao copiar um objeto, apenas o próprio objeto e as variáveis ​​básicas no objeto são copiados, e o objeto apontado pela referência contida no objeto não é copiado
  • 深拷贝, Não apenas copia o próprio objeto, mas também todos os objetos apontados pelas referências contidas no objeto de cópia

Dar uma castanha

Aqui, Usuário e Telefone são usados ​​como exemplos.
O método principal usado para testar a cópia superficial e a cópia profunda é o seguinte:

public class CloneTest {
    
    
    public static void main(String[] args) throws CloneNotSupportedException {
    
    
        // 预置数据
        Phone phone1 = new Phone();
        String number = "11111111111";
        phone1.setPhoneNum(number);
        String name = new String("dkangel");
        int age = 24;

        User user1 = new User(name, age, phone1);
        User user2 = (User) user1.clone();
        System.out.println("对象是否相等:" + (user1 == user2));
        System.out.println("类的类型是否相等:" + (user1.getClass() == user2.getClass()));
        System.out.println("age属性是否相等:" + (user1.getAge() == user2.getAge()));
        System.out.println("name属性是否相等:" + (user1.getName() == user2.getName()));
        System.out.println("对象的对象属性Phone是否相等:" + (user1.getPhone() == user2.getPhone()));
    }
}
Cópia superficial

Copie apenas o próprio objeto, Phone não precisa implementar a interface Cloneable e substituir o método clone ().

public class Phone {
    
    
    private String phoneNum;

    public String getPhoneNum() {
    
    
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
    
    
        this.phoneNum = phoneNum;
    }
}
public class User implements Cloneable {
    
    
    private String name;
    private int age;
    private Phone phone;

    public User(String name, int age, Phone phone) {
    
    
        this.name = name;
        this.age = age;
        this.phone = phone;
    }

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public Phone getPhone() {
    
    
        return phone;
    }

    public void setPhone(Phone phone) {
    
    
        this.phone = phone;
    }

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

user2是user1的浅拷贝,只拷贝user1对象本身,未拷贝成员变量phone,所以两者phone对象相等
Insira a descrição da imagem aqui

Cópia profunda

Não apenas copie o próprio objeto, mas também copie todos os objetos apontados pelo objeto, portanto, a classe Phone também suporta clone.

public class Phone implements Cloneable{
    
    
    private String phoneNum;

    public String getPhoneNum() {
    
    
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
    
    
        this.phoneNum = phoneNum;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
    
    
        return super.clone();
    }
}

User.java apenas cole o método clone () aqui, os outros são consistentes com o clone raso

public class User implements Cloneable {
    
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    
        User user = (User) super.clone();
        user.phone = (Phone) user.getPhone().clone();
        return user;
    }
}

user2是user1的深拷贝,拷贝user1本身的同时也拷贝一份phone1对象,两者phone对象不再相等
Insira a descrição da imagem aqui

Compreenda a cópia superficial e a cópia profunda em combinação com a partição de memória JVM

Insira a descrição da imagem aqui
Como você pode ver na figura acima, a memória JVM é dividida em cinco partes: heap, área de método, contador de programa, pilha de máquina virtual e pilha de método local. Aqui, nos concentramos apenas em

  • Objeto de armazenamento
  • Armazene tipos de dados básicos e referências de objetos虚拟机栈
  • Armazenar informações básicas方法区
浅拷贝解读

Interprete o método principal de CloneTest de cima para baixo no modo e obtenha o diagrama de distribuição dos seguintes objetos na JVM.
Aqui usamos o 句柄模式objeto de acesso (e o modo de endereço direto), uma interpretação simples

O novo objeto phone1 é armazenado no pool de instâncias do heap; o número da string é criado entre aspas, portanto, é armazenado no pool de constantes da string no heap; o nome da string é criado com new, por isso é armazenado no Pool de instâncias de string; idade pertence aos dados básicos. O tipo é, portanto, armazenado na pilha de máquina virtual; o usuário1 aloca memória no heap e cria o objeto usuário2 por meio dos dados do próprio objeto clone usuário1 e os atributos nome / idade / o telefone do usuário2 são compartilhados com o usuário1.

Insira a descrição da imagem aqui

深拷贝解读

O user2 criado pela cópia profunda não compartilha mais o atributo phone com o objeto user1. A cópia profunda não apenas copia o próprio user1, mas também copia o objeto phone1 do usuário1.

Apenas as diferenças da cópia superficial são coladas aqui,user2的phone属性由指向phone1改为指向phone2
Insira a descrição da imagem aqui

Se houver algum erro, sinta-se à vontade para apontá-lo, paz

Acho que você gosta

Origin blog.csdn.net/Dkangel/article/details/106032094
Recomendado
Clasificación