簡體   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