克隆

为什么要克隆

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()方法中手动给克隆出来的非基本数据类型(引用类型)赋值。

原文地址:https://www.cnblogs.com/tp123/p/6403067.html