Heim  >  Artikel  >  Java  >  Detaillierte Analyse des flachen Klonens und tiefen Klonens in Java-Objekten (mit Beispielen)

Detaillierte Analyse des flachen Klonens und tiefen Klonens in Java-Objekten (mit Beispielen)

不言
不言nach vorne
2018-10-10 11:19:301997Durchsuche

Dieser Artikel bietet Ihnen eine detaillierte Analyse des flachen Klonens und des tiefen Klonens in Java-Objekten. Ich hoffe, dass er für Sie hilfreich ist.

Einführung:

In der Object-Basisklasse gibt es eine Methode namens clone, die einen Klon des vorherigen Objekts generiert Wenn es Referenztypen gibt, gibt es tiefes Klonen. Der Unterschied zwischen flachem Klonen und flachem Klonen besteht darin, dass, wenn das geklonte Objekt ein Referenztypattribut enthält, beim tiefen Klonen eine vollständige Kopie des Attributs erstellt wird, während beim flachen Klonen nur eine Referenz kopiert wird zum Attribut. Schauen wir uns zunächst einige kleinere Probleme an, die einfach zu erstellen sind.

Die Clone-Methode gehört zur Object-Klasse, nicht zur Cloneable-Schnittstelle. Die Marker-Schnittstelle verwendet Benutzermarkierungen Implementieren Sie die Schnittstelle. Es gibt drei gängige Markierungsschnittstellen: Serializable, Cloneable und RandomAccess. Wenn die Cloneable-Schnittstelle nicht implementiert ist, führt der Aufruf der Clone-Methode zu einer CloneNotSupportedException.

Die Klonmethode in der Object-Klasse wird mit protected geändert. Das bedeutet, dass, wenn wir diese Methode in der Unterklasse nicht überschreiben, außerhalb der Unterklasse nicht darauf zugegriffen werden kann, da nur auf diese geschützte Berechtigung zugegriffen werden kann Das Objekt kann darauf zugreifen, was auch die Aussage bestätigt, dass Unterklassen den Berechtigungsmodifikator vergrößern können, wenn sie Methoden der übergeordneten Klasse überschreiben, aber nicht kleiner.

protected native Object clone() throws CloneNotSupportedException;

Intern wird lediglich die Klonmethode der übergeordneten Klasse aufgerufen, um die Zugriffsrechte zu erweitern. Dies ist jedoch nicht der Fall Sie müssen es umschreiben, wenn Sie in der Zukunft erben. Natürlich ist es nur die Klonfunktion für das flache Klonen, und das tiefe Klonen muss geändert werden.

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

Wenn das Attribut String ist und String auch eine Klasse ist, ist der String-Referenztyp? String verhält sich wie ein Basistyp. Nach dem Klonen verweisen die beiden Referenzen auf denselben String. Wenn jedoch einer von ihnen geändert wird, wird der Wert des Strings nicht geändert Die geänderte Referenz zeigt auf die neue Zeichenfolge. Das Aussehen ähnelt dem Grundtyp.

Flaches Klonen:

Flaches Klonen bedeutet, dass Referenztypattribute nicht vollständig kopiert werden können. Das Klassenattribut Mark besteht aus Chinesisch, Mathematik usw. Beispiele für flaches Klonen Fehler

class Mark{
    private int chinese;
    private int math;
    public Mark(int chinese, int math) {
        this.chinese = chinese;
        this.math = math;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public void setMath(int math) {
        this.math = math;
    }

    @Override
    public String toString() {
        return "Mark{" +
                "chinese=" + chinese +
                ", math=" + math +
                '}';
    }
}
public class User implements Cloneable{
    private String name;
    private int age;
    private Mark mark;

    public User(String name, int age,Mark mark) {
        this.name = name;
        this.age = age;
        this.mark = mark;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", mark=" + mark +
                '}';
    }

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

    public static void main(String[] args) throws CloneNotSupportedException {
        Mark mark = new Mark(100,99);
        User user = new User("user",22,mark);
        User userClone = (User) user.clone();
        System.out.println("原user:"+user);
        System.out.println("克隆的user:"+userClone);
        //修改引用类型的mark属性
        user.mark.setMath(60);
        System.out.println("修改后的原user:"+user);
        System.out.println("修改后的克隆user:"+userClone);
    }
}

Das Ausgabeergebnis ist:   

Ursprünglicher Benutzer: User{name='user', age=22, mark=Mark{chinese=100, math=99}}
Klonbenutzer: User{name='user', age=22, mark=Mark{chinese=100, math=99}}
Geänderter ursprünglicher Benutzer: User{name='user', age=22, mark=Mark {chinese=100, math=60}}
Modifizierter Klonbenutzer: Benutzer{name='user', age=22, mark=Mark{chinese=100, math=60}}

Das ist es Es ist klar, dass nach der Änderung der Markierung des Benutzers auch der geklonte Benutzer geändert wird. Und wenn Sie nicht betroffen sein möchten, müssen Sie tiefgreifend klonen.

Deep Cloning:

Methode 1: Verschachtelte Aufrufe der Klonfunktion

Da der Referenztyp nicht vollständig geklont werden kann, implementiert der Referenztyp auch die Cloneable-Schnittstelle und schreibt den Klon neu method , die Klonmethode in der Benutzerklasse ruft die Klonmethode des Attributs auf, d ='user', age =22, mark=Mark{chinese=100, math=99}}

 Benutzer klonen: User{name='user', age=22, mark=Mark{chinese=100, math= 99}}

Der modifizierte ursprüngliche Benutzer: User{name='user', age=22, mark=Mark{chinese=100, math=60}}

Der modifizierte Klonbenutzer: User{name='user ', age =22, mark=Mark{chinese=100, math=99}}


Methode 2: Serialisierung

Die vorherige Methode reicht aus, um unsere Anforderungen zu erfüllen, aber wenn die vorhanden sind Viele Beziehungen oder einige Attribute sind Arrays. Arrays können die klonbare Schnittstelle nicht implementieren (wir können das Array in der Klonmethode manuell kopieren), aber wir müssen die Klonmethode jedes Mal von Hand schreiben, was sehr mühsam ist, und die Serialisierungsmethode Jede Klasse muss nur eine serialisierbare Schnittstelle implementieren, die auch eine Markierungsschnittstelle ist. Schließlich werden die Serialisierungs- und Deserialisierungsvorgänge verwendet, um den Zweck des Klonens (einschließlich des Kopierens von Arrays) zu erreichen. Informationen zur Serialisierung und Deserialisierung finden Sie im nächsten Artikel

class Mark implements Cloneable{
    private int chinese;
    private int math;
    public Mark(int chinese, int math) {
        this.chinese = chinese;
        this.math = math;
    }
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }
    public void setMath(int math) {
        this.math = math;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Mark{" +
                "chinese=" + chinese +
                ", math=" + math +
                '}';
    }
}
public class User implements Cloneable{
    private String name;
    private int age;
    private Mark mark;

    public User(String name, int age,Mark mark) {
        this.name = name;
        this.age = age;
        this.mark = mark;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", mark=" + mark +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        User user = (User) super.clone();
        user.mark = (Mark) this.mark.clone();
        return user;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Mark mark = new Mark(100,99);
        User user = new User("user",22,mark);
        User userClone = (User) user.clone();
        System.out.println("原user:"+user);
        System.out.println("克隆的user:"+userClone);
        //修改引用类型的mark属性
        user.mark.setMath(60);
        System.out.println("修改后的原user:"+user);
        System.out.println("修改后的克隆user:"+userClone);
    }
}

Ausgabeergebnis:

Ursprünglicher Benutzer: User{name='user', age=22, mark=Mark{chinese= 100, math=99}}

Klonbenutzer: User{name='user', age=22, mark=Mark{chinese=100, math=99}}

Geänderter ursprünglicher Benutzer: User{ name=' user', age=22, mark=Mark{chinese=100, math=60}}

  Modifizierter Klonbenutzer: User{name='user', age=22, mark=Mark{chinese= 100, math=99 }}


 Mit Array-Attribut klonen

import java.io.*;
class Mark implements Serializable {
    private int chinese;
    private int math;
    public Mark(int chinese, int math) {
        this.chinese = chinese;
        this.math = math;
}
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }
    public void setMath(int math) {
        this.math = math;
    }
    @Override
    public String toString() {
        return "Mark{" +
                "chinese=" + chinese +
                ", math=" + math +
                '}';
    }
}
public class User implements Serializable{
    private String name;
    private int age;
    private Mark mark;

    public User(String name, int age,Mark mark) {
        this.name = name;
        this.age = age;
        this.mark = mark;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", mark=" + mark +
                '}';
    }
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Mark mark = new Mark(100,99);
        User user = new User("user",22,mark);

        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(user);//序列化
        ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
        ObjectInputStream oi = new ObjectInputStream(bi);
        User userClone = (User) oi.readObject();//反序列化

        System.out.println("原user:"+user);
        System.out.println("克隆的user:"+userClone);
        user.mark.setMath(59);
        System.out.println("修改后的原user:"+user);
        System.out.println("修改后的克隆user:"+userClone);
    }
}

Das obige ist der detaillierte Inhalt vonDetaillierte Analyse des flachen Klonens und tiefen Klonens in Java-Objekten (mit Beispielen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen