引例
说到java的克隆你还记得多少? 一说到克隆你可能就会想起来那个接口, 没错, 他就是Cloneable
Cloneable是java里面内置的很常用的接口, 我们说 Object类中也有一个clone方法:
但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常.
于是, 我们创建一个类为Dog类, 如下:
public class Main { public static void main(String[] args) throws CloneNotSupportedException { Dog dog1 = new Dog(); Dog dog2 = (Dog) dog1.clone(); System.out.println(dog1 == dog2); } } class Dog implements Cloneable { public String dogName; public int dogAge; @Override protected Object clone() throws CloneNotSupportedException { Dog newDog = null; newDog = (Dog) super.clone(); return newDog; } }
输出结果:
深克隆 vs 浅克隆
浅克隆只复制对象本身和对象的本数据类型字段,而不复制引用类型字段所指向的对象.
这里的引用类型, 可以是类的引用, 也可以是字符串等.
我们说实现了Cloneable接口的类拷贝出来的对象是浅拷贝还是深拷贝???
案例:
public class Main { public static void main(String[] args) throws CloneNotSupportedException { Animal animal1 = new Animal(); Animal animal2 = (Animal) animal1.clone(); animal2.classIn = 2; animal2.dog.name = "小白"; System.out.println(animal1.toString()); System.out.println(animal2.toString()); } } class Dog { String name = "小黑"; } class Animal implements Cloneable { public Dog dog = new Dog(); public int classIn = 1; @Override public String toString() { return "Animal{" + "dogName=" + dog.name + ", classIn=" + classIn + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
输出结果:
可以看出来, 他们里面的类的实例却是共享的, 里面的类的引用不同, 但是引用的是同一个类对象. 这就是浅拷贝.
如何深克隆
深克隆:基本数据类型变量和引用类型变量指向的对象都会被复制,即针对引用类型的成员变量真正的复制一份,重新开辟空间保存,这样两个引用类型属性互不影响。
那么如何进行深拷贝呢??
很容易想到的一点就是, 在重写object中的clone方法, 然后对被克隆的类里面的类引用继续克隆. 也就是嵌套克隆
public class Main { public static void main(String[] args) throws CloneNotSupportedException { Animal animal1 = new Animal(); Animal animal2 = (Animal) animal1.clone(); animal2.classIn = 2; animal2.dog.name = "小白"; System.out.println(animal1.toString()); System.out.println(animal2.toString()); } } class Dog implements Cloneable{ String name = "小黑"; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Animal implements Cloneable { public Dog dog = new Dog(); public int classIn = 1; @Override public String toString() { return "Animal{" + "dogName=" + dog.name + ", classIn=" + classIn + '}'; } @Override protected Object clone() throws CloneNotSupportedException { Animal newAnimal = (Animal) super.clone(); newAnimal.dog = (Dog) dog.clone(); return newAnimal; } }
输出结果: