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

33

在Java中为什么要使用clone()方法?(请从内存限制的角度回答)这会减少内存使用吗?如果是,那么如何减少?这会减少内存泄漏的影响吗?


我们不使用它。我在18年中从未使用过它,也没有使用“复制构造函数”。 - user207421
在这里深入了解:http://howtodoinjava.com/core-java/cloning/a-guide-to-object-cloning-in-java/comment-page-1/#comment-25762 - Bharatesh
7个回答

22

除了不要使用clone,而是实现一个复制构造函数,你还关心内存限制。

克隆的想法是创建克隆对象的精确副本。因此,在最坏情况下,之后会使用两倍的内存。实际上——稍微少一点,因为字符串经常被interned,通常不会被克隆。即使这取决于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
如果Sheep扩展了一些基类,比如Animal,该基类具有需要调用的属性。那么,复制构造函数方法是否意味着* Animal Sheep *都具有复制构造函数,并且Sheep CC必须调用super(sheep) - Adam Parkin
1
是的。调用将是 super(sheep);,超类将根据该实例初始化其字段。无论如何,您都需要调用超类的(一个)构造函数。 - Andreas Dolk

17

7

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()方法。

4

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


3
首先,复制一个对象似乎是一项简单直接的任务:只需将所有属性的值复制到同一类的另一个实例中即可。但是,对于引用其他对象的变量怎么办?这些引用值的副本意味着它们将指向与第一个类相同的对象。
但也许这不是我们想要的。也许我们希望由副本引用的所有对象都是独立的副本。
这两种类型的对象副本被称为:
浅拷贝 - 原始对象的所有属性的精确位拷贝 深拷贝 - 原始对象的原语被精确复制,但引用的对象被复制而不是引用本身。 Object类是所有Java类继承的类,其中包括clone()方法,该方法将使所有属性的精确位拷贝。
然而,clone()是一个受保护的方法。因此,除了该对象的类的子类外,任何类的实例都不能克隆给定的对象(除非它们是该对象的类的子类)。这允许类设计者明确指定要进行哪种克隆(浅层或深层)。
Java要求想要重写clone()方法的类实现cloneable接口。还必须将clone()方法设置为public,以覆盖访问限制。
例如,HashTable类实现了cloneable接口。它的clone()方法进行浅拷贝,因此复制的HashTable的键和值将引用与原始对象相同的对象。
然而,许多核心Java类并未实现cloneable接口。如果为这样的类调用clone()方法,则会导致CloneNotSupportedException。

0

查看克隆约束

简单来说,它用于复制对象而不是引用,这会增加内存使用量。


0

我们应该避免使用clone() 这里是一个好例子Here


那是一些奇怪的建议。克隆应该不比任何其他深度复制对象的方法更难实现。唯一的区别是clone将从浅层复制开始,如果所有字段都是基元和/或不可变对象,则可能完成所需的所有工作。建议在新类中实现带有异常的clone而没有讨论是错误的。例如,如果您将新类传递给使用基类上的 clone 的方法,则代码将失败。 - user904963

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接