【问题标题】:Why do we use the clone() method in Java?为什么我们在 Java 中使用 clone() 方法?
【发布时间】:2011-08-13 17:06:50
【问题描述】:

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

【问题讨论】:

标签: java clone


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      除了不要使用克隆,实现一个复制构造函数,你问过内存限制。

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

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

      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);
      

      【讨论】:

      • 如果 Sheep 扩展了一些基类,比如Animal,它也有需要调用的属性。复制构造函数方法是否意味着 both AnimalSheep 都有复制构造函数,而 Sheep CC 必须调用 super(sheep)
      • 是的。调用将是super(sheep);,超类将基于该实例初始化其字段。无论如何,您都需要调用超类的(一个)构造函数。
      【解决方案4】:

      复制一个对象起初似乎是一项简单的任务:

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

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

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

      浅拷贝 - 原始对象所有属性的精确位拷贝 深度复制 - 原语被精确复制,但被引用的对象被复制而不是引用本身。 所有 Java 类都继承的 Object 类包括 clone() 方法,该方法将对所有属性进行精确的位复制。

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

      Java 需要想要覆盖 clone() 方法的类来实现可克隆接口。 clone() 方法必须公开,以便覆盖访问限制。

      例如,HashTable 类实现可克隆。它的 clone() 方法进行了浅拷贝,因此复制的 HashTable 的键和值将引用与原始对象相同的对象。

      但是,许多核心 Java 类不实现可克隆。如果为此类类调用 clone() 方法,则会导致 CloneNotSupportedException。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          clone constraints

          简而言之,它用于复制对象而不是引用,它增加了内存使用量。

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              猜你喜欢
              • 2016-12-28
              • 2010-11-07
              • 1970-01-01
              • 2017-10-13
              • 2013-03-10
              • 1970-01-01
              • 2022-01-06
              • 2013-06-26
              • 1970-01-01
              相关资源
              最近更新 更多