在 Java 中,重写 clone 方法时为什么需要将其声明为 public?

java 8object oriented programmingprogramming更新于 2025/11/15 13:00:17

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 和 Student 数据,如下所示。

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。


相关文章