一.Cloneable 的用途
Cloneable和Serializable一样都是标记型接口,它们内部都没有方法和属性,implements Cloneable表示该对象能被克隆,能使用Object.clone()方法。如果没有implements Cloneable的类调用Object.clone()方法就会抛出CloneNotSupportedException。
二.克隆的分类
(1)浅克隆(shallow clone),浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
(2)深克隆(deep clone),深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
举例区别一下:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2中包含对C2(C1的copy)的引用。
三.克隆的举例
要让一个对象进行克隆,其实就是两个步骤:
1. 让该类实现java.lang.Cloneable接口;
2. 重写(override)Object类的clone()方法。
Demo:
1.浅克隆
public class Animal implements Cloneable{ private int age; private String name; public Object clone() throws CloneNotSupportedException{ return super.clone(); } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
测试类:
public class TestMain { public static void main(String[] args) throws Exception { Animal animal1 = new Animal(); animal1.setAge(12); animal1.setName("狮子"); Animal animal2 = (Animal) animal1.clone(); //animal2.setName("老虎"); System.out.println("类型比较:"+(animal1==animal2)); System.out.println("基本数据类型比较:"+(animal1.getAge()==animal2.getAge())); System.out.println("引用数据类型地址比较:"+(animal1.getName()==animal2.getName())); System.out.println("引用数据类型内容比较:"+(animal1.getName().equals(animal2.getName()))); System.out.println("引用数据类型内容:"+animal1.getName()+"/"+animal2.getName()); } }
输出结果:
类型比较:false
基本数据类型比较:true
引用数据类型地址比较:true
引用数据类型内容比较:true
引用数据类型内容:狮子/狮子
2.深克隆
public class Animal implements Cloneable{ private int age; private String name; public Object clone() throws CloneNotSupportedException{ Animal animal = (Animal) super.clone(); animal.name = new String(this.name); return animal; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
测试类:
public class TestMain { public static void main(String[] args) throws Exception { Animal animal1 = new Animal(); animal1.setAge(12); animal1.setName("狮子"); Animal animal2 = (Animal) animal1.clone(); //animal2.setName("老虎"); System.out.println("类型比较:"+(animal1==animal2)); System.out.println("基本数据类型比较:"+(animal1.getAge()==animal2.getAge())); System.out.println("引用数据类型地址比较:"+(animal1.getName()==animal2.getName())); System.out.println("引用数据类型内容比较:"+(animal1.getName().equals(animal2.getName()))); System.out.println("引用数据类型内容:"+animal1.getName()+"/"+animal2.getName()); } }
测试结果:
类型比较:false
基本数据类型比较:true
引用数据类型地址比较:false
引用数据类型内容比较:true
引用数据类型内容:狮子/狮子
总结:浅克隆是把该对象的基本数据及引用地址复制,深克隆是把该对象的基本数据以及对象copy到另一个地址