繁体   English   中英

为什么在实现clone方法时我们返回super.clone()而不是这个clone()

[英]Why when implementing clone method we return super.clone() not this clone()

public abstract class Shape implements Cloneable {

   private String id;
   protected String type;

   abstract void draw();

   public String getType(){
      return type;
   }

   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

   public Object clone() {
      Object clone = null;

      try {
         clone = super.clone();

      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }

      return clone;
   }
}

假设我想获得一个对象的克隆然后我们总是返回super.clone()如果我想克隆一个对象然后我想这是我想要克隆的对象。我是克隆的初学者。

超类clone方法应该是Object.clone()或者它应该将1 (最终)委托给Object.clone() 这是一个“神奇”的方法,它知道如何创建当前实例的实际类的新实例。

当然,如果你试图像这样实现克隆:

public Object clone() {
    return clone();
}

你会创建一个快速以StackOverflowError结束的递归循环。


1 - 如果super.clone()最终没有委托给Object.clone() ,那么它将无法克隆Shape定义的字段的值及其具体的子类型。


请注意,这个特定的例子, clone()可以简化为:

public Object clone() {
    return super.clone();
}

Shape类将Object作为其超类,并且Object.clone()将抛出CloneNotSupportedException的唯一情况是实际类没有implement Cloneable接口。 但是Shape就是这样做的。

事实上。 clone()所有声明实际上都是为了提高Object API中protectedclone()版本的可见性。

无论你使用super还是this ,被解除引用的对象都是相同的。 但是,由于您使用this.clone()覆盖clone方法会导致(无限)递归。 使用super.clone()确保调用超类的clone实现。

请注意,无论实际类型如何, Object.clone复制整个对象。

覆盖方法时,您唯一需要注意的是:

  • 增加public的可见度(如果你想要的话)
  • 复制从类中引用但未被super.clone()复制的任何可变对象

以下示例显示了克隆对象的常用方法

public class Sheep implements Cloneable {

    private String name;

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

    public static void main(String[] args) throws CloneNotSupportedException {
        Sheep s = new Sheep("dolly");
        Sheep s2 = (Sheep) s.clone();
        s2.numbers[0] = 42;
        System.out.println(s);
        System.out.println(s2);
    }

    private int[] numbers = new int[1];

    @Override
    public Object clone() throws CloneNotSupportedException {
        Sheep clone = (Sheep) super.clone();

        // copy referenced mutable objects
        clone.numbers = this.numbers.clone();

        // no need to copy name, since String is immutable

        return clone;
    }

    @Override
    public String toString() {
        return "Sheep{" + "name=" + name + ", numbers=" + Arrays.toString(numbers) + '}';
    }

}

请注意,注释掉该行

clone.numbers = this.numbers.clone();

将导致阵列相同。

在您的示例中, super.clone()引用了Object.clone()其JavaDoc声明:

否则,此方法创建此对象的类的新实例,并使用该对象的相应字段的内容初始化其所有字段,就像通过赋值一样; 这些字段的内容本身不会被克隆。 因此,该方法执行该对象的“浅拷贝”,而不是“深拷贝”操作。

这意味着如果浅拷贝就足够了,那么使用super.clone()就足够了。 覆盖有两个目的:

  • make clone() public( Object.clone()受保护)
  • 通过打印stacktrace并返回null处理子类不能正常实现Cloneable

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM