1. 想要克隆一个对象,对这个类有两个要求:
(1)实现Cloneable接口,这是一个标记接口,只有实现了这个接口的类才能被克隆
class person implements Cloneable{
}
(2)重写Clone方法,并在里面调用访问父类的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
注意:要重写的原因:因为Object中的clone方法是proteced修饰的,一直以来,对于protected的理解只是这样的:
protected native Object clone() throws CloneNotSupportedException;
protected 修饰的类和属性,对于自己、本包和其子类可见
但protected准确的理解是这样的:
对于protected的成员或方法,要分子类和父类是否在同一个包中。
与父类不在同一个包中的子类,只能访问自身从父类继承而来的受保护成员,
而不能访问父类实例本身的受保护成员。
在相同包时,protected和public是一样的
(3)拷贝
public class Pratices12 {
public static void main(String[] args) throws CloneNotSupportedException {
person p1=new person("老王",13);
//用对象调用clone方法,拷贝
Object cloneP = p1.clone();
if(cloneP instanceof person){
person p3=(person)cloneP;
System.out.println(p3);
}
}
}
2.拷贝的分类:
(1)浅拷贝:
当一个类中的成员不仅有基本数据类型,而且还有引用数据类型的时候,如果该类在重写父类的clone方法时,仅仅只是调用父类的clone方法,那此时拷贝的仅仅只是该类,而该类中的引用数据类型还是原来的那一份,最直接的体现就是,当我们修改了该引用数据类型,那么本体和克隆体都会被修改,这就成为浅拷贝
//子类重写父类的Clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
代码演示:
首先有一个Dog类
class Dog{
String name;
public Dog() {
}
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
}
有一个人的类,人的类里有一只狗的引用
class person implements Cloneable{
private String name;
private int age;
private Dog dog;//狗的引用
public person() {
}
public person(String name, int age,Dog dog) {
this.name = name;
this.age = age;
this.dog=dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "person{" +
"name='" + name + '\'' +
", age=" + age +
", dog=" + dog +
'}';
}
//子类重写父类的Clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
拷贝并修改拷贝体中的dog的名字
public class Pratices12 {
public static void main(String[] args) throws CloneNotSupportedException {
person p1=new person("老王",13,new Dog("小白"));
//拷贝
person cloneP = (person)p1.clone();
//修改克隆体中狗的名字
cloneP.getDog().setName("小黑");
//打印本体和克隆体
System.out.println(p1);
System.out.println(cloneP);
}
}
打印效果
person{name='老王', age=13, dog=Dog{name='小黑'}}
person{name='老王', age=13, dog=Dog{name='小黑'}}
结论:本体和克隆体里的狗名字全部修改了
原理图:
(2)深拷贝:
如果该类在重写父类的clone方法时,再调用完父类的方法后,也把dog拷贝了,那就称为深拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
person cloneP = (person) super.clone();
cloneP.dog=(Dog) this.dog.clone();
return cloneP;
}
注意:此时Dog也要求实现实现Cloneable接口,和重写clone方法,才能完成克隆
此时再修改,本体就不会被修改了
person{name='老王', age=13, dog=Dog{name='小白'}}
person{name='老王', age=13, dog=Dog{name='小黑'}}