Sök…


Anmärkningar

Kloning kan vara svårt, särskilt när objektets fält innehåller andra objekt. Det finns situationer där du vill utföra en djup kopia , istället för att bara kopiera fältvärdena (dvs. referenser till andra objekt).

Den nedersta raden är klon är trasig , och du bör tänka två gånger innan du implementerar det Cloneable gränssnittet och åsidosätter clone . clone deklareras i Object och inte i gränssnittet Cloneable , så Cloneable misslyckas med att fungera som ett gränssnitt eftersom det saknar en offentlig clone . Resultatet är att kontraktet för användning av clone är tunt dokumenterat och svagt verkställt. Till exempel, en klass som åsidosätter clone förlitar sig ibland på alla sina överordnade klasser som också åsidosätter clone . De tvingas inte göra det, och om de inte gör det kan din kod kasta undantag.

En mycket bättre lösning för att tillhandahålla kloningsfunktionalitet är att tillhandahålla en kopieringskonstruktör eller kopieringsfabrik . Se Joshua Blochs effektiva Java- punkt 11: Överväga klon på ett klokt sätt.

Kloning med en kopieringskonstruktör

Ett enkelt sätt att klona ett objekt är genom att implementera en kopieringskonstruktör.

public class Sheep {

    private String name;

    private int weight;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    // copy constructor
    // copies the fields of other into the new object
    public Sheep(Sheep other) {
        this.name = other.name;
        this.weight = other.weight;
    }

}

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly = new Sheep(sheep); // dolly.name is "Dolly" and dolly.weight is 20

Kloning genom att implementera Clonable interface

Kloning av ett objekt genom att implementera Cloneable- gränssnittet.

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

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

}

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly =  (Sheep) sheep.clone(); // dolly.name is "Dolly" and dolly.weight is 20

Kloning utför en ytlig kopia

Standardbeteende vid kloning av ett objekt är att utföra en ytlig kopia av objektets fält. I så fall har både det ursprungliga objektet och det klonade objektet referenser till samma objekt.

Detta exempel visar det beteendet.

import java.util.List;

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    private List<Sheep> children;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

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

    public List<Sheep> getChildren() {
        return children;
    }

    public void setChildren(List<Sheep> children) {
        this.children = children;
    }

}

import java.util.Arrays;
import java.util.List;

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);

// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);

sheep.setChildren(Arrays.asList(child1, child2));

// clone the sheep
Sheep dolly =  (Sheep) sheep.clone();
List<Sheep> sheepChildren = sheep.getChildren();
List<Sheep> dollysChildren = dolly.getChildren();
for (int i = 0; i < sheepChildren.size(); i++) {
    // prints true, both arrays contain the same objects
    System.out.println(sheepChildren.get(i) == dollysChildren.get(i));
}

Kloning utför en djup kopia

För att kopiera kapslade objekt måste en djup kopia utföras, som visas i det här exemplet.

import java.util.ArrayList;
import java.util.List;

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    private List<Sheep> children;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Sheep clone = (Sheep) super.clone();
        if (children != null) {
            // make a deep copy of the children
            List<Sheep> cloneChildren = new ArrayList<>(children.size());
            for (Sheep child : children) {
                cloneChildren.add((Sheep) child.clone());
            }
            clone.setChildren(cloneChildren);
        }
        return clone;
    }

    public List<Sheep> getChildren() {
        return children;
    }

    public void setChildren(List<Sheep> children) {
        this.children = children;
    }

}

import java.util.Arrays;
import java.util.List;

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);

// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);

sheep.setChildren(Arrays.asList(child1, child2));

// clone the sheep
Sheep dolly =  (Sheep) sheep.clone();
List<Sheep> sheepChildren = sheep.getChildren();
List<Sheep> dollysChildren = dolly.getChildren();
for (int i = 0; i < sheepChildren.size(); i++) {
    // prints false, both arrays contain copies of the objects inside
    System.out.println(sheepChildren.get(i) == dollysChildren.get(i));
}

Kloning med en kopieringsfabrik

public class Sheep {

    private String name;
    
    private int weight;
    
    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }
    
    public static Sheep newInstance(Sheep other);
        return new Sheep(other.name, other.weight)
    }

}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow