重寫clone方法時,為什麼需要在Java中將其宣告為public?


**clone()** 方法屬於java.lang包中名為Object的類,它接受一個物件作為引數,建立一個並返回它的副本。

為了使用此方法,您需要確保您的類實現了Cloneable(標記)介面。

示例

 線上演示

public class CloneExample implements Cloneable {
   private String name;
   private int age;
   public CloneExample(String name, int age){
      this.name = name;
      this.age = age;
   }
   public void displayData(){
      System.out.println("Name : "+this.name);
      System.out.println("Age : "+this.age);
   }
   public static void main(String[] args) throws CloneNotSupportedException {
      CloneExample std = new CloneExample("Krishna", 25);
      System.out.println("Contents of the original object");
      std.displayData();
      System.out.println("Contents of the copied object");
      CloneExample copiedStd = (CloneExample) std.clone();
      copiedStd.displayData();
   }
}

輸出

Contents of the original object
Name : Krishna
Age : 25
Contents of the copied object
Name : Krishna
Age : 25

使用clone方法,您可以執行兩種型別的複製:

  • 淺複製 - 複製物件時,如果它包含任何物件作為欄位,則只複製對這些物件的引用,而不是完整的物件。預設情況下,**clone()** 方法執行淺複製。
  • 深複製 - 在深複製中,原始物件的全部欄位都被精確複製,此外,如果它包含任何物件作為欄位,則也會建立它們的副本(使用clone()方法)。

因此,要執行深複製,您需要重寫Object類的clone()方法。

clone()方法的訪問修飾符

java.lang.Object 類中的clone()方法是受保護的(protected)。方法之前的protected修飾符使其僅對當前類的子類可見。由於Object是Java中所有類的超類,因此在Object類中的clone()方法之前使用protected修飾符是有意義的。

如果您重寫Object類的clone()方法並將其宣告為protected,則它僅對當前類的子類可見。

示例

假設我們在名為**myPackage1**的包中擁有兩個類,名為Contact和StudentData,如下所示。

Contact.java

package myPackage1;
public class Contact implements Cloneable{
   private long phoneNo;
   private String email;
   public Contact(long phoneNo, String email ){
      this.phoneNo = phoneNo;
      this.email = email;
   }
   public void displayContact() {
      System.out.println("Phone no: "+this.phoneNo);
      System.out.println("Email: "+this.email);
   }
   protected Object clone() throws CloneNotSupportedException{
      return super.clone();
   }
}

StudentData.java

package myPackage1;
public class StudentData implements Cloneable {
   private String name;
   private int age;
   private Contact contact;
   public StudentData(String name, int age, Contact contact){
      this.name = name;
      this.age = age;
      this.contact = contact;
   }
   public void displayData(){
      System.out.println("Name : "+this.name);
      System.out.println("Age : "+this.age);
      contact.displayContact();
   }
   protected Object clone() throws CloneNotSupportedException{
      StudentData student = (StudentData) super.clone();
      student.contact = (Contact) contact.clone();
      return student;
   }
}

您可以編譯以上兩個類:

D:\>javac -d . Contact.java
D:\>javac -d . StudentData.java

從另一個名為myPackage的包中的類,我們嘗試訪問StudentData類的clone()方法,如下所示:

示例

package myPackage2;
import myPackage1.Contact;
import myPackage1.StudentData;
public class CloneExample{
   public static void main(String[] args) throws CloneNotSupportedException {
      //Creating an object of the class
      StudentData std = new StudentData("Krishna", 25, new Contact(9848022338L, "Krishna_test@mymail.com"));
      //Creating a clone of the above object
      StudentData copiedStd = (StudentData) std.clone();
      System.out.println("Contents of the copied object::");
      copiedStd.displayData();
      System.out.println(" ");
      System.out.println("Contents of the original object::");
      std.displayData();
   }
}

編譯時錯誤

當您嘗試編譯上面的類時,由於您嘗試訪問實現的clone()方法(它被宣告為protected),並且是從另一個包中訪問的,因此會生成編譯時錯誤,如下所示:

D:\>javac -d . CloneExample.java
CloneExample.java:10: error: clone() has protected access in StudentData
   StudentData copiedStd = (StudentData) std.clone();
                                             ^
1 error

因此,在重寫clone()方法時,建議將其宣告為public而不是protected,以便可以從系統中任何位置的類訪問它。

在重寫方法時,子類中的方法不能比超類中的方法具有更高的訪問限制。由於public的限制比protected低,因此允許將重寫方法中的訪問修飾符從protected更改為public。

更新於:2019年9月10日

2K+ 瀏覽量

開啟您的職業生涯

透過完成課程獲得認證

開始學習
廣告
© . All rights reserved.