Maison  >  Article  >  Java  >  Méthodes de copie profonde et de copie superficielle de l'interface Java Cloneable

Méthodes de copie profonde et de copie superficielle de l'interface Java Cloneable

PHPz
PHPzavant
2023-04-28 08:49:131072parcourir

    Code source de l'interface cloneable

    Interface clonable :

    La classe qui implémente cette interface - on peut en déduire que la méthode clone() peut être légalement appelée - pour implémenter des instances de classe : attribut à attribut copier. java.lang.Object

    Si une classe n'implémente pas l'interface Cloneable, une CloneNotSupportedException sera levée lorsque la méthode clone() est appelée.

    Généralement,

    les sous-classes qui implémentent l'interface Cloneable doivent remplacer la méthode clone() avec un accès public (bien que la méthode clone dans la classe java.Object soit de type protégé)

    Il faut comprendre que l'interface Cloneable ne incluez la méthode clone(), par conséquent, si vous implémentez simplement l'interface Cloneable, vous ne pourrez pas cloner l'objet normalement

    [Raison : même si la méthode clone est appelée de manière réfléchie, il n'y a aucune garantie qu'elle réussira]&mdash ;—Personnel La compréhension est la suivante :

    Cela est dû au fait de savoir s'il faut remplacer la méthode Clone() ou au problème de "copie superficielle et copie profonde".

    class Pet implements Cloneable{
        //properties
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public Pet() {
        }
        public Pet(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Pet{" +
                    "name='" + name + '\'' +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pet pet = (Pet) o;
            return Objects.equals(name, pet.name);
        }
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    //    @Override
    //    public Pet clone() {
    //        try {
    //            return (Pet)super.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
    }

    Cas de copie superficielle

    Définition de la classe Pet

    Remarque : la classe Pet implémente l'interface Cloneable, mais ne remplace pas la méthode Clone() (évidemment : la classe Pet n'a pas la possibilité de cloner des objets pour le moment ).

    class Pet implements Cloneable{
        //properties
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public Pet() {
        }
        public Pet(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Pet{" +
                    "name='" + name + '\'' +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pet pet = (Pet) o;
            return Objects.equals(name, pet.name);
        }
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    //    @Override
    //    public Pet clone() {
    //        try {
    //            return (Pet)super.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
    }

    Définition de la classe Person

    Remarque : La classe Person implémente l'interface Cloneable et remplace également la méthode Clone(). Alors, la classe Person a-t-elle la capacité de cloner des objets ? (En raison du problème de copie superficielle, cette capacité de clonage d'objet est considérée comme incomplète et défectueuse).

    class Pet implements Cloneable{
        //properties
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public Pet() {
        }
        public Pet(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Pet{" +
                    "name='" + name + '\'' +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pet pet = (Pet) o;
            return Objects.equals(name, pet.name);
        }
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    //    @Override
    //    public Pet clone() {
    //        try {
    //            return (Pet)super.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
    }

    Problème de copie superficielle - test de code

    Pourquoi est-il dit : La capacité de clonage d'objets de la classe Person est incomplète et défectueuse pour le moment ? Car à ce stade, lorsque la méthode clone() est appelée via l'objet Person et que l'objet est cloné, le clone de la valeur de son attribut membre pet (un objet de la classe Pet) n'est qu'une simple copie de l'adresse mémoire dans la zone du tas.

    C'est-à-dire : pour parler franchement, la valeur de l'attribut pet de l'objet Person et l'objet cloné partagent la même zone de mémoire de tas. Le problème est évident : lorsque l'attribut pet de l'objet cloné est défini, cela affectera évidemment la valeur de l'attribut pet de l'objet Person d'origine.

    La démonstration du code est la suivante :

      //methods
        public static void main(String[] args) throws CloneNotSupportedException {
            testPerson();
        }
        public static void testPerson() throws CloneNotSupportedException {
            Person p=new Person("张三",14,new Pet("小黑"));
            System.out.println(p);
            Person clone = (Person)p.clone();
            System.out.println(clone);
            System.out.println(p.equals(clone));
            System.out.println(p.getPet()==clone.getPet());
            System.out.println("************");
            clone.setAge(15);
            System.out.println(p);
            System.out.println(clone);
            System.out.println(p.equals(clone));
            System.out.println("************");
            clone.getPet().setName("小黄");
            System.out.println(p);
            System.out.println(clone);
            System.out.println(p.equals(clone));
            System.out.println(p.getPet()==clone.getPet());
        }

    Méthodes de copie profonde et de copie superficielle de linterface Java Cloneable

    Cas de copie profonde

    Alors, comment implémenter la copie profonde ? La clé réside dans les lignes de code commentées dans le cas ci-dessus. La classe Pet remplace la méthode clone(). :

    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