Maison  >  Article  >  Java  >  Parlez de votre compréhension du clonage profond et du clonage superficiel en Java

Parlez de votre compréhension du clonage profond et du clonage superficiel en Java

王林
王林avant
2021-01-30 09:53:352204parcourir

Parlez de votre compréhension du clonage profond et du clonage superficiel en Java(Explication : Cet article porte sur la différence et la méthode de mise en œuvre entre le clonage profond et le clonage superficiel ?)

Parler ne coûte pas cher#

J'ai rencontré du clonage profond et superficiel (copie profonde, copie superficielle) plus de une fois récemment. Question, à part l'impression qu'il existe une méthode de clonage, je suis confus ! ! ! Le clonage (copie) est une opération courante en Java pour obtenir rapidement une copie d'un objet. Le clonage est divisé en clonage profond et clonage superficiel.

Clonage superficiel : Créez un nouvel objet. Les propriétés du nouvel objet sont exactement les mêmes que celles de l'objet d'origine. Pour les propriétés de type non basiques, elles pointent toujours vers l'adresse mémoire de l'objet pointé. par les propriétés originales.

Clonage profond : créez un nouvel objet, et les autres objets référencés dans les attributs seront également clonés et ne pointeront plus vers l'adresse de l'objet d'origine.

En bref, le clonage profond et superficiel allouera une nouvelle zone dans le tas. La différence réside dans le fait que l'objet référencé par l'attribut object doit être cloné (de manière récursive).

Montrer ma photo#

pos : l'adresse de l'objet actuel ;

fils : l'adresse pointée par l'attribut fils

nom ; : le nom de la propriété de l'objet.

(Recommandations associées :

Tutoriel d'introduction à Java

)

Montrez-vous mon code#

Parlez de votre compréhension du clonage profond et du clonage superficiel en Javacase1 :

public class Son implements Serializable , Cloneable{    private String name;    private Son son;    public Son() {        super();
    }    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public Son getSon() {        return son;
    }    public void setSon(Son son) {        this.son = son;
    }    @Override
    public String toString() {        return super.toString();
    }    @Override
    protected Object clone() throws CloneNotSupportedException {        return super.clone();
    }
}

Test

public static void main(String[] args) throws Exception{	// 创建父亲(LiLiu),儿子(LiWu),孙子(LiLiu)并关联
	Son father = new Son();
	father.setName("LiSi");
	Son son = new Son();
	son.setName("LiWu");
	Son grandSon = new Son();
	grandSon.setName("LiLiu");
	father.setSon(son);
	son.setSon(grandSon);	// 调用clone方法
	Son fatherCopy =  (Son) father.clone();	boolean flag1 = fatherCopy==father;	boolean flag2 = fatherCopy.getSon() == son;	boolean flag3 = fatherCopy.getSon().getSon() == grandSon;	// 比较克隆后的地址
	System.out.println(flag1);// false
	System.out.println(flag2);// true
	System.out.println(flag3);// true
	// 比较Name
	flag1= fatherCopy.getName()==father.getName();
	flag2 = fatherCopy.getSon().getName() == son.getName();
	flag3 = fatherCopy.getSon().getSon().getName() == grandSon.getName();
	System.out.println(flag1);// true
	System.out.println(flag2);// true
	System.out.println(flag3);// true
	
	//将对象写到流里    
	ByteArrayOutputStream byteOut=new ByteArrayOutputStream();    
	ObjectOutputStream objOut=new ObjectOutputStream(byteOut);    
	objOut.writeObject(father);	//从流里读出来    
	ByteArrayInputStream byteIn=new ByteArrayInputStream(byteOut.toByteArray());    
	ObjectInputStream objInput=new ObjectInputStream(byteIn);
    fatherCopy = (Son) objInput.readObject();
	flag1= fatherCopy==father;
	flag2 = fatherCopy.getSon() == son;
	flag3 = fatherCopy.getSon().getSon() == grandSon;
	System.out.println(flag1);// false
	System.out.println(flag2);// false
	System.out.println(flag3);// false
	
	// 比较Name
	flag1= fatherCopy.getName()==father.getName();
	flag2 = fatherCopy.getSon().getName() == son.getName();
	flag3 = fatherCopy.getSon().getSon().getName() == grandSon.getName();
	System.out.println(flag1);// false
	System.out.println(flag2);// false
	System.out.println(flag3);// false}
À partir du code ci-dessus et des résultats d'exécution, il n'est pas difficile de voir que si l'objet implémente Cloneable et remplace la méthode clone sans effectuer aucune opération, l'appel de clone est un clone superficiel. Utiliser des flux d'objets pour écrire des objets dans le flux, puis les lire constitue un clonage profond.

Réflexion : Depuis l'implémentation de l'interface Cloneable et la réécriture de l'interface de clonage, on ne peut effectuer qu'un clonage superficiel. Cependant, si les attributs de type référence de la classe (et les attributs de type référence de l'attribut) sont clonés superficiellement, jusqu'à ce qu'il n'y ait pas d'attribut de type référence ou que l'attribut de type référence soit nul, un clone profond sera formé dans son ensemble. L'attribut de type de référence de l'objet et l'attribut de type d'application de l'attribut implémentent Coloneable, remplacent la méthode clone et l'appellent dans la méthode clone.

protected Object clone() throws CloneNotSupportedException {
      Son result = (Son) super.clone();	if (son != null) {
		result.son = (Son) son.clone();
	}    return result;
}

Personnellement, je pense que lors du choix de la méthode de clonage profond, elle doit être basée sur la complexité de l'objet, par exemple si l'attribut de type de référence a plusieurs couches de relations d'attributs de type de référence. Si l'objet n'a qu'une ou deux couches d'attributs de type référence, il est plus pratique de choisir la méthode mentionnée dans la réflexion. Sinon, utilisez le flux d'objet.

Pour plus de questions d'entretien connexes, veuillez visiter :

questions et réponses d'entretien Java

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer