重写clone方法时,为什么需要在Java中将它声明为public?
clone()方法属于java.lang包的名为Object的类,它在创建参数时接受一个对象并返回其副本。
为了使用此方法,您需要确保您的类实现了Cloneable(marker)接口。
例子
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()方法。
clone()方法的访问说明符
java.lang.Object类中的clone()方法受到保护。方法之前的受保护说明符仅可用于当前类的子类,因为Object是Java中所有类的超类,因此在对象类中的clone()方法之前的受保护说明符才有意义。
如果重写对象类的clonemethod()并声明它为受保护的对象,则只能访问当前类的子类。
例
假设我们在名为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(); } }
编译时错误
当您尝试编译上述类时,由于您尝试访问已声明为protected的实现的clone()方法,因此会从另一个包中生成编译时错误,如下所示:
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的限制低于受保护的限制,因此可以使用重写方法将访问说明从受保护的更改为public。