为什么要克隆
package algorithm; public class Person { private String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String toString(){ return "name="+name; } }
public class Test{
public static void main(String[] args) throws Exception { Person person1 = new Person("a"); System.out.println("person1:"+person1); Person person2 = person1; System.out.println("person2:"+person2); System.out.println("person2中name修改为b"); person2.setName("b"); System.out.println("person1:"+person1); }
}
person1:name=a
person2:name=a
person2中name修改为b
person1:name=b
这就是没有克隆出现的问题,因为只是引用的赋值,它们指向同一对象,如果一个修改另一个也会影响。所以我们需要克隆一个对象,让它们指向不同的对象。
Object的clone()被声明为proctected,那么根据http://www.cnblogs.com/tp123/p/6406576.html中对protected的描述,可以知道我们想要某个类使用clone方法,就必须在该类中重写clone方法(否则就只能在该类中调用)。
对于上面的就是在Person里面可以通过this.clone()或super.clone(),new Person().clone()来调用,但是在Test中就不可以通过Person person1 = new Person("a");person1.clone();Test自身也是可以调用。
但是要求调用clone方法的对象必须实现cloneable,如果没有实现该接口就会报错。
所以一般要使用clone方法
1.实现cloneable接口,表示这是一个可clone的对象。
2.重写一个public的clone方法。
克隆的例子
package algorithm; public class Person implements Cloneable{ private String name; public Person() { System.out.println("执行person的构造方法"); } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Person clone() throws CloneNotSupportedException { return (Person)super.clone(); } public String toString(){ return "name="+name; } }
public static void main(String[] args) throws Exception{ Person p1 = new Person(); p1.setName("person1"); System.out.println("p1:"+p1); Person p2 = p1.clone(); System.out.println("p2:"+p2); p2.setName("person2"); System.out.println("p2修改后"); System.out.println("p1:"+p1); System.out.println("p2:"+p2); }
结果
执行person的构造方法 p1:name=person1 p2:name=person1 p2修改后 p1:name=person1 p2:name=person2
从结果可以看出
1.java克隆调用的根本还是Object的克隆方法。
2.clone方法并没有调用构造方法。(因为只有一次调用构造方法,是new的时候调用的)。 clone方法是一个native方法,应该是c++直接内存复制产生一个新对象。
3.调用clone方法确实产生了新的对象,所以修改person2的内容不会修改person1。
浅克隆和深克隆
1.浅克隆,就是表层的克隆,也就是只对最外层的对象进行克隆,而里面的所有引用的对象并没有克隆,只克隆了这些对象的地址。
2.深克隆,就是除了克隆自己也克隆所有里面的对象实例。
如果要深克隆,有两种办法。
1.对对象序列化,然后反序列化。
2.先调用super.clone()方法克隆出一个新对象来,然后在子类的clone()方法中手动给克隆出来的非基本数据类型(引用类型)赋值。