首页 > 代码库 > Java对象的复制方法总结

Java对象的复制方法总结

 参考:《Java经典编程》实例054~058,《Java7 入门经典》

1.   使用构造函数复制对象

 
   对象是传址调用,直接通过“=”来进行连接是并没有达到复制对象的目的。下面这样的类可以通过构造函数来复制对象。局限在于,要求生成对象的类的域仅仅是基本类型,没有其他引用类型。如果有引用类型,则新对象仅仅复制了引用类型的副本,他们指向同一个对象,这是浅复制。除非对该引用类型也再次进行构造函数的复制,直到所有复制都针对的是基本类型,这是深复制。

  根据《Java7 入门经典》P250页6.8.3节的说法,跟第二类的复杂的克隆相比,构造函数法是复制对象方法的最佳实践。

第一类:域只有基本类型

public class Employee {
	private String name;
	private int age;
	/**
	 * 构造函数复制对象
	 */
	public Employee(Employee employee) {
		// TODO Auto-generated constructor stub
		name=employee.getName();
		age=employee.getAge();
	}
/**
	 * 初始化
	 */
	public Employee(String name,int age) {
		// TODO Auto-generated constructor stub
		this.name=name;
		this.age=age;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "姓名:"+name+",年龄"+age;
	}
//省略set()和get()函数
} 

第二类:域有引用类型Addres address,需要对其也进行构造函数复制
/**  
 * 创建时间:2014年9月8日 下午2:38:13  
 * 项目名称:Test  
 * @author Cao Yanfeng  
 * @since JDK 1.6.0_21  
 * 类说明:  
 */
public class Employee {
	private String name;
	private int age;
	private Address address;
	/**
	 * 初始化
	 */
	public Employee(String name,int age,Address address) {
		// TODO Auto-generated constructor stub
		this.name=name;
		this.age=age;
		this.address=new Address(address);
	}
	/**
	 * 构造函数复制
	 */
	public Employee(Employee employee) {
		// TODO Auto-generated constructor stub
		name=employee.getName();
		age=employee.getAge();
		address=<span style="font-family: Arial, Helvetica, sans-serif;">new Address(</span><span style="font-family: Arial, Helvetica, sans-serif;">employee.getAddress()</span><span style="font-family: Arial, Helvetica, sans-serif;">)</span>;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "姓名:"+name+",年龄:"+age+",地址——"+address;
	}
	//省略set()和get()函数	
}


/**
 * 创建时间:2014年9月8日 下午2:52:18 项目名称:Test
 * 
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21 类说明:
 */
public class Address {
	private String state;
	private String province;
	private String city;
	/**
	 * 构造函数实现复制
	 */
	public Address(Address address) {
		// TODO Auto-generated constructor stub
		state=address.state;
		province=address.province;
		city=address.city;
	}


	/**
	 * 初始化
	 */
	public Address(String state, String province, String city) {
		// TODO Auto-generated constructor stub
		this.state = state;
		this.province = province;
		this.city = city;
	}


	@Override
	public String toString() {
		// TODO Auto-generated method stub
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("国家:" + state + ",");
		stringBuilder.append("省:" + province + ",");
		stringBuilder.append("市:" + city);
		return stringBuilder.toString();
	}
//省略set()和get()函数
} 

2.   对象克隆

  克隆的效果和使用构造函数复制对象高度一致,局限在于,要求生成对象的类的域仅仅是基本类型,没有其他引用类型。如果有引用类型,则新对象仅仅复制了引用类型的副本,他们指向同一个对象,并没有对其进行克隆,这是浅克隆。除非对该引用类型也再次进行clone,直到所有clone都针对的是基本类型,这就是深度克隆。
注意,所有类都要实现Cloneable接口,并重写clone()方法。
第一类:域只有基本类型
/
**
 * 创建时间:2014年9月8日 下午2:38:13 项目名称:Test
 * 
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21 类说明:
 */
public class Employee implements Cloneable {
	private String name;
	private int age;
	/**
	 * 初始化
	 */
	public Employee(String name, int age) {
		// TODO Auto-generated constructor stub
		this.name = name;
		this.age = age;
	}
	 @Override
	protected Employee clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		Employee employee = null;
		employee = (Employee) super.clone();
		return employee;
	}


	@Override
	public String toString() {
		// TODO Auto-generated method stub
		// return "姓名:"+name+",年龄:"+age+",地址——"+address;
		return "姓名:" + name + ",年龄:" + age;
	}


//省略set()和get()函数
}


第二类:域有引用类型Addres address,需要对其也进行clone
/**
 * 创建时间:2014年9月8日 下午2:38:13 项目名称:Test
 * 
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21 类说明:
 */
public class Employee implements Cloneable {
	private String name;
	private int age;


	 private Address address;
	/**
	 * 
	 */
	public Employee(String name, int age,Address address) {
		// TODO Auto-generated constructor stub
		this.name = name;
		this.age = age;
		this.address=address;
	}
	// @Override
	protected Employee clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		Employee employee = null;
		employee = (Employee) super.clone();
		employee.address=address.clone();
		return employee;
	}


	@Override
	public String toString() {
		// TODO Auto-generated method stub
		 return "姓名:"+name+",年龄:"+age+",地址——"+address;


	}
//省略set()和get()函数
}
/**
 * 创建时间:2014年9月8日 下午2:52:18 项目名称:Test
 * 
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21 类说明:
 */
public class Address implements Cloneable{
	private String state;
	private String province;
	private String city;
	/**
	 * 初始化
	 */
	public Address(String state, String province, String city) {
		// TODO Auto-generated constructor stub
		this.state = state;
		this.province = province;
		this.city = city;
	}
	


	@Override
	protected Address clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		Address address=null;
		address=(Address)super.clone();
		return address;
	}




	@Override
	public String toString() {
		// TODO Auto-generated method stub
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("国家:" + state + ",");
		stringBuilder.append("省:" + province + ",");
		stringBuilder.append("市:" + city);
		return stringBuilder.toString();
	}
//省略set()和get()函数
}

3.   对象序列化

  对象序列化即把待复制的对象从内存写到本地文件中,然后再从本地文件读到出内存中并赋给新的引用。对象序列号实现了深度克隆。
  注意,待序列化化的对象要实现Serializable接口,域中如果有引用类型,也要实现Serializable接口,否则序列化出错。
 
 /**  
 * 创建时间:2014年9月8日 下午2:36:34  
 * 项目名称:Test  
 * @author Cao Yanfeng  
 * @since JDK 1.6.0_21  
 * 类说明:  
 */
public class ObjectCloneTest {


	/**
	 * @param args
	 * @throws CloneNotSupportedException 
	 */
	public static void main(String[] args) throws CloneNotSupportedException  {
		// TODO Auto-generated method stub
		Address address=new Address("中国", "北京", "北京");
		Employee employee=new Employee("曹艳丰",23,address);
		System.out.println(employee);
		Employee employee2=null;
		
		ObjectOutputStream out=null;
		ObjectInputStream in=null;
		try {
			out=new ObjectOutputStream(new FileOutputStream("employee.dat"));
			out.writeObject(employee);
			in=new ObjectInputStream(new FileInputStream("employee.dat"));
			employee2=(Employee)in.readObject();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(employee2);


	}


}
  /**
 * 创建时间:2014年9月8日 下午2:38:13 项目名称:Test
 * 
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21 类说明:
 */
public class Employee implements Serializable {
	/**
	 * 序列号
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;


	private Address address;


	/**
	 * 
	 */
	public Employee(String name, int age, Address address) {
		// TODO Auto-generated constructor stub
		this.name = name;
		this.age = age;
		this.address = address;
	}


	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "姓名:" + name + ",年龄:" + age + ",地址——" + address;


	}
//省略set()和get()函数
}
/**
 * 创建时间:2014年9月8日 下午2:52:18 项目名称:Test
 * 
 * @author Cao Yanfeng
 * @since JDK 1.6.0_21 类说明:
 */
public class Address implements Serializable{
	/**
	 *序列号 
	 */
	private static final long serialVersionUID = 1L;
	private String state;
	private String province;
	private String city;
	/**
	 * 初始化
	 */
	public Address(String state, String province, String city) {
		// TODO Auto-generated constructor stub
		this.state = state;
		this.province = province;
		this.city = city;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("国家:" + state + ",");
		stringBuilder.append("省:" + province + ",");
		stringBuilder.append("市:" + city);
		return stringBuilder.toString();
	}
//省略set()和get()函数
}



Java对象的复制方法总结