◎筱米加步枪◎.Blog

Happy coding

Java深克隆(序列化方式)

对于Java的克隆技术,标准的方式是:首先实现Cloneable接口,然后重写clone方法,调用父类clone进行克隆。

介绍另外一种方法,该方法的原理:

利用流将序列化的对象写在流里,因为写在流里面的对象就是原对象的一份拷贝,而原对象还在Java虚拟机里(JVM)里,再从流里面读取出来得到的对象就是得到一份克隆对象。

注意:需要克隆的对象必须实现Serializable接口

接着之前的场景,看下面的例子:

public class User implements Serializable{
	
	private static final long serialVersionUID = 1L;

	private String userName;

	private Address address;
	
	public User(String userName) {
		super();
		this.userName = userName;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public Object copy() throws IOException, ClassNotFoundException{
		//将对象序列化后写在流里,因为写在流里面的对象是一份拷贝,
		//原对象仍然在JVM里
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bos);
		oos.writeObject(this);
		
		ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
				bos.toByteArray()));
		return ois.readObject();
	}
}
public class Address implements Serializable{
	
	private static final long serialVersionUID = 1L;
	
	private String addressName;
	
	public Address(String addressName) {
		super();
		this.addressName = addressName;
	}

	public String getAddressName() {
		return addressName;
	}

	public void setAddressName(String addressName) {
		this.addressName = addressName;
	}
}
/**
 * 测试克隆-深克隆(使用序列化的方式进行深克隆)
 * 深克隆不但克隆当前的对象,而且还克隆该对象所引用的对象
 * @author CST
 */
public class TestClone {

	public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
		User chen = new User("CST");
		chen.setAddress(new Address("福州"));
		
		User liu = (User) chen.copy();
		liu.setUserName("LXF");
		liu.getAddress().setAddressName("泉州");
		System.out.println(chen.getUserName()+"="+chen.getAddress().getAddressName());
	}
}

输出结果:CST=福州
效果同实现Cloneable接口方式一样

Java克隆技术

前些天,根据需要,加入了克隆技术,学习了下,总结如下:

Java的对象都是引用,当将一个对象赋值给另外一个对象的时候,也就是说指针(当然,java没有指针的概念)同指向同一块内存地址,这个时如果对一个对象进行修改,也必然会修改另外一个对象的值,这明显不是我们想要的,解决这个问题,可以引入克隆技术,我们可以克隆一个对象出来,使得对克隆出来的对象修改不会改变原始对象的值。

克隆分为:浅克隆和深克隆。

浅克隆是指:浅克隆只是克隆当前的对象,不克隆该对象所应用的对象

深克隆是指:深克隆不但克隆当前的对象,而且还克隆该对象所引用的对象

看具体实例:

(模拟场景:用户对象、地址对象、用户对象拥有地址对象)

一、浅克隆

//克隆必须实现Cloneable,调用父类的clone()方法
public class User implements Cloneable{
	
	private String userName;

	private Address address;
	
	public User(String userName) {
		super();
		this.userName = userName;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	/*
	 * 克隆当前对象,得到克隆后的对象
	 * @see java.lang.Object#clone()
	 */
	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
//地址对象
public class Address{ 
	
	private String addressName;
	
	public Address(String addressName) {
		super();
		this.addressName = addressName;
	}

	public String getAddressName() {
		return addressName;
	}

	public void setAddressName(String addressName) {
		this.addressName = addressName;
	}
}
/**
 * 测试克隆-浅克隆
 * 浅克隆只是克隆当前的对象,不克隆该对象所应用的对象
 * @author CST
 */
public class TestClone {

	public static void main(String[] args) throws CloneNotSupportedException {
		User chen = new User("CST");
		chen.setAddress(new Address("福州"));
		
		User liu = (User) chen.clone();
		liu.setUserName("LXF");
		liu.getAddress().setAddressName("泉州");
		System.out.println(chen.getUserName()+"="+chen.getAddress().getAddressName());
	}
}

输出结果:CST=泉州

可以看到,虽然User对象可以单独操作,但是视图去修改User下的Address值,仍然是改变了原始用户下的Address值

二、深克隆:

public class User implements Cloneable{
	
	private String userName;

	private Address address;
	
	public User(String userName) {
		super();
		this.userName = userName;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	//克隆
	@Override
	public Object clone() throws CloneNotSupportedException {
		//克隆对象的同时,也克隆user下的应用对象Address
		User user = (User) super.clone();
		Address address = (Address) user.getAddress().clone();
		user.setAddress(address);
		return user;
	}
}
public class Address implements Cloneable{
	
	private String addressName;
	
	public Address(String addressName) {
		super();
		this.addressName = addressName;
	}

	public String getAddressName() {
		return addressName;
	}

	public void setAddressName(String addressName) {
		this.addressName = addressName;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

测试类同上,

输出结果:CST=长乐

这样,才是我们想要的结果。无论修改当前对象还是当前对象所包含的对象,都是两个独立的操作,互不影响。