簡體   English   中英

調用super.clone()方法時向下轉換

[英]Downcasting while calling super.clone() method

考慮以下程序

class A implements Cloneable {
    String str = null;
    public void set(String str)
    {
        this.str = str;      
    }

    @Override
    public A clone()
    {
         A a = null;
         try {
              a = (A) super.clone();
              if(a.str!=null) {
                  System.out.println(a.str);
              }
              else {
                  System.out.println("null");
              }

         } 
         catch (CloneNotSupportedException e) {
               e.printStackTrace();
         }
         return a;    
    }
    public static void main (String args[])
    {
        A a = new A();
        a.set("1234");
        A b = a.clone();
    }
}

為什么上述程序的輸出是1234而不是null。

我期待null,因為對我的理解如下。

  1. super.clone()方法將創建一個父類型的新對象(在本例中為Object),其中父類的屬性將被淺復制。

  2. 當我們在clone()方法中進行向下轉換時,子類中定義的屬性將使用其默認值進行初始化,因為這是一個新對象。

但是在查看輸出之后,似乎子類(this)的當前實例的屬性值被復制到新構造的對象中(在調用父類的克隆並向下轉換之后)。

有人能告訴我們當我們垂頭喪氣時發生了什么嗎?

正確的結果是1234 ...讓我們看看原因:

創建一個新的A實例:

A a = new A();

將值設置為A.str

a.set("1234");

克隆一個

A b = a.clone();

首先,請注意,我們正在使用實例a clone()方法,所以我們去那里:

@Override
public A clone()
{
     // create a NEW instance, it does not set a to null!!!
     // to reference the caller (a.clone in main) 
     // you must use this keyword i.e: this.str = null
     A a = null;
     try {
          // call Cloneable::clone() method 
          a = (A) super.clone();

          // now a is filled with data of this instance so print 1234
          if(a.str!=null) {
              System.out.println(a.str);
          }
          // unused code in this case
          else {
              System.out.println("null");
          }

     } 
     catch (CloneNotSupportedException e) {
           e.printStackTrace();
     }
     // return cloned instance
     return a;    
}

來自Object#clone文檔。

創建並返回此對象的副本。 “復制”的確切含義可能取決於對象的類別。 通常的意圖是,對於任何對象x,表達式:

x.clone()!= x

將為真,並且該表達式:

x.clone()。getClass()== x.getClass()

是正確的,但這不是絕對要求。 通常情況是:

x.clone()。equals(x)

是真的,這不是絕對要求。

如您所見,典型的情況是X.equals(XClone) == true 對於您而言,情況並非如此,因為A沒有覆蓋equals方法。

另外:

類Object的方法clone執行特定的克隆操作。

[...]

該方法創建該對象類的新實例,並使用該對象相應字段的內容完全初始化其所有字段,就像通過賦值一樣; 字段的內容本身不會被克隆。 因此,此方法執行此對象的“淺復制”,而不是“深復制”操作。

如本文檔所述,本機實現只是創建您要克隆的對象的shallow copy 由於這種行為,正確的輸出是1234而不是null ,因為類中的fields只是分配給了克隆的實例。

super.clone()方法將創建一個父類型的新對象(在這種情況下為Object)

不,這是您要出問題的地方。 Object.clone()將創建一個新的實例,該實例與調用它的對象的運行時類相同,該運行時類是A ,而不是Object 它將把被調用對象中A所有字段淺拷貝到新對象中。

當我們在clone()方法中進行向下轉換時,子類中定義的屬性將使用其默認值進行初始化,因為這是一個新對象。

這沒有任何意義,因為強制轉換引用將永遠不會影響所指向對象的狀態。 如果引用所指向的對象還不是A的實例,則強制轉換將拋出ClassCastException 如果強制轉換成功,則意味着引用指向的對象已經是A的實例,而您只是使用不同類型的引用指向同一對象。 您將永遠不會獲得帶有演員表的“新對象”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM