为什么我们在Java中使用clone()方法?

时间:2011-04-27 09:43:31

标签: java clone

为什么我们在Java中使用clone()方法? (请给出关于内存约束的答案。)这会减少内存使用量吗?如果是,那怎么样?这会减少内存泄漏的影响吗?

7 个答案:

答案 0 :(得分:19)

除了不使用clone,实现一个拷贝构造函数,你问了内存约束。

克隆的想法是创建克隆对象的精确副本。因此,在最坏的情况下,之后使用两倍的内存量。实际上 - 少一点,因为字符串经常被实习并且(通常)不会被克隆。即使它取决于克隆方法/复制构造函数的实现者。

这是一个带有复制构造函数的类的简短示例:

public class Sheep {
  private String name;
  private Fur fur;
  private Eye[2] eyes;
  //...

  // the copy constructor
  public Sheep(Sheep sheep) {
    // String already has a copy constructor ;)
    this.name = new String(sheep.name);

    // assuming Fur and Eye have copy constructors, necessary for proper cloning
    this.fur = new Fur(sheep.fur); 
    this.eyes = new Eye[2];
    for (int i = 0; i < 2; i++) 
       eyes[i] = new Eye(sheep.eyes[i]);
  }
}

用法:

Sheep dolly = getDolly();  // some magic to get a sheep
Sheep dollyClone = new Sheep(dolly);

答案 1 :(得分:14)

我们应该使用它。 It is a broken and obsolete idiom,在新代码中应避免使用。最好尽可能使用复制构造函数。

答案 2 :(得分:8)

clone()将对象的值复制到另一个。 clone()方法保存了额外的处理任务,用于创建对象的精确副本。

正如您在下面的示例中所看到的,两个引用变量具有相同的值。

class Student18 implements Cloneable {

    int rollno;
    String name;

    Student18(int rollno, String name) {

        this.rollno = rollno;
        this.name = name;
    }

    public static void main(String args[]) {

        try {
            Student18 s1 = new Student18(101, "amit");

            Student18 s2 = (Student18) s1.clone();

            System.out.println(s1.rollno + " " + s1.name);
            System.out.println(s2.rollno + " " + s2.name);

        } catch (CloneNotSupportedException c) {
        }

    }

    public Object clone() throws CloneNotSupportedException {

        return super.clone();
    }
} 

输出

101 amit
101 amit

如果我们通过new关键字创建另一个对象并将另一个对象的值分配给此对象,则需要对该对象进行大量处理。因此,为了保存额外的处理任务,我们使用clone()方法。

答案 3 :(得分:4)

如果我们需要使用具有相同数据的许多对象,则不要使用new关键字创建对象。使用clone方法创建该对象,因为使用clone方法创建对象的操作比使用new关键字更快。

答案 4 :(得分:3)

制作对象的副本最初似乎是一项直接的任务:

只需将所有属性的值复制到同一个类的另一个实例中即可。 但是引用其他对象的变量呢?这些参考值的副本意味着它们将指向与第一类相同的对象。

但也许这不是我们想要的。也许我们希望副本引用的所有对象也是独立的副本。

这两种类型的对象副本称为:

浅拷贝 - 原始对象的所有属性的精确位拷贝 深度复制 - 精确复制基元,但复制引用的对象而不是引用本身。 Object类由所有Java类继承,包括clone()方法,该方法将为所有属性创建精确的位副本。

但是,clone()是受保护的方法。因此,无法通过包外的任何类的实例克隆给定对象(除非它们是该对象类的子类)。这允许类设计者明确指定要制作的克隆类型(浅或深)。

Java要求类重写clone()方法,以实现可克隆接口。 clone()方法也必须公开,以覆盖访问限制。

例如,HashTable类实现了cloneable。它的clone()方法生成一个浅拷贝,因此复制的HashTable的键和值将引用与原始对象相同的对象。

但是,许多核心Java类不实现cloneable。如果为此类调用clone()方法,将导致CloneNotSupportedException。

答案 5 :(得分:0)

请参阅clone constraints

用几句话来表示它用于复制对象而不是引用,它会增加内存使用量。

答案 6 :(得分:0)

我们应该避免使用clone() Here就是一个很好的例子