代码改变世界

java对象克隆和序列化

2011-09-09 09:27  Rollen Holt  阅读(8888)  评论(3编辑  收藏  举报

先用一个例子来说明假克隆吧,也就是用“=”之后的效果、。

public class Employee{
	public Employee(){

	}

	public Employee(String name, int age){
		this.age = age;
		this.name = name;
	}

	@Override
	public String toString(){
		return "姓名: " + name + "年龄: " + age;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}

	public int getAge(){
		return age;
	}

	public void setAge(int age){
		this.age = age;
	}

	public static void main(String[] args){
		Employee demo1 = new Employee("rollen", 20);
		System.out.println(demo1);
		Employee demo2 = demo1;
		demo2.setAge(100);
		demo2.setName("hello world");
		System.out.println(demo1);
		System.out.println(demo2);
	}

	private String name;
	private int age;
}

【运行结果】:

【运行结果】

姓名: rollen年龄: 20

姓名: hello world年龄: 100

姓名: hello world年龄: 100


下面看看java中的浅拷贝

对于类中的每个域,如果只包含基本类型或者不可变的引用类型,如String,或者对象在其生命周期内不会发生变化,则可以使用浅拷贝来复制对象,但是一般使用深拷贝。

class Address{
	public Address(){

	}

	public Address(String state, int number){
		this.number = number;
		this.state = state;
	}

	@Override
	public String toString(){
		return "state: " + state + " munber: " + number;
	}

	public String getState(){
		return state;
	}

	public void setState(String state){
		this.state = state;
	}

	public int getNumber(){
		return number;
	}

	public void setNumber(int number){
		this.number = number;
	}

	private String state;
	private int number;
}

public class Employee implements Cloneable{
	public Employee(){

	}

	public Employee(String name, int age, Address address){
		this.address = address;
		this.age = age;
		this.name = name;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}

	public int getAge(){
		return age;
	}

	public void setAge(int age){
		this.age = age;
	}

	public Address getAddress(){
		return address;
	}

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

	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		sb.append("name:" + name + ", ");
		sb.append("age:" + age + " \n");
		sb.append("Address: " + address);
		return sb.toString();
	}

	@Override
	protected Employee clone(){
		Employee employee = null;
		try{
			employee = (Employee) super.clone();
		}catch(CloneNotSupportedException e){
			e.printStackTrace();
		}
		return employee;
	}

	public static void main(String[] args){
		System.out.println("克隆之前:");
		Address add1 = new Address("中国", 1);
		Employee emp1 = new Employee("rollen", 20, add1);
		System.out.println(emp1);
		System.out.println("克隆之后");
		Employee emp2 = emp1.clone();
		emp2.setName("hello world");
		emp2.setAge(100);
		emp2.address.setNumber(2);
		emp2.address.setState("美国");
		System.out.println(emp1);
		System.out.println("-----");
		System.out.println(emp2);
	}

	private String name;
	private int age;
	private Address address;
}

【运行结果】:

克隆之前:

name:rollen, age:20

Address: state: 中国 munber: 1

克隆之后

name:rollen, age:20

Address: state: 美国 munber: 2

-----

name:hello world, age:100

Address: state: 美国 munber: 2

 

但是上面的主函数中的:

// emp2.address.setNumber(2);
// emp2.address.setState("美国");

替换为:

emp2.setAddress(new Address("美国", 2));

运行结果为:

克隆之前:

name:rollen, age:20

Address: number: 1state中国

 

克隆之后

name:rollen, age:20

Address: number: 1state中国

 

-----

name:hello world, age:100

Address: number: 2state美国

 

这里我有点不明白了,为什么这种情况下克隆之后两个address会不一样呢?

谁帮忙指点一下,谢谢了、

现在看看java对象的深克隆

class Address implements Cloneable{
	public Address(){

	}

	public Address(String state, int number){
		this.number = number;
		this.state = state;
	}

	@Override
	public String toString(){
		return "state: " + state + " munber: " + number;
	}

	@Override
	protected Address clone() throws CloneNotSupportedException{
		Address address = null;
		address = (Address) super.clone();
		return address;
	}

	public String getState(){
		return state;
	}

	public void setState(String state){
		this.state = state;
	}

	public int getNumber(){
		return number;
	}

	public void setNumber(int number){
		this.number = number;
	}

	private String state;
	private int number;
}

public class Employee implements Cloneable{
	public Employee(){

	}

	public Employee(String name, int age, Address address){
		this.address = address;
		this.age = age;
		this.name = name;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}

	public int getAge(){
		return age;
	}

	public void setAge(int age){
		this.age = age;
	}

	public Address getAddress(){
		return address;
	}

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

	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		sb.append("name:" + name + ", ");
		sb.append("age:" + age + " \n");
		sb.append("Address: " + address);
		return sb.toString();
	}

	@Override
	protected Employee clone(){
		Employee employee = null;
		try{
			employee = (Employee) super.clone();
			employee.address = address.clone();		}catch(CloneNotSupportedException e){
			e.printStackTrace();
		}
		return employee;
	}

	public static void main(String[] args){
		System.out.println("克隆之前:");
		Address add1 = new Address("中国", 1);
		Employee emp1 = new Employee("rollen", 20, add1);
		System.out.println(emp1);
		System.out.println("克隆之后");
		Employee emp2 = emp1.clone();
		emp2.setName("hello world");
		emp2.setAge(100);
		emp2.setAddress(new Address("美国", 2));
		System.out.println(emp1);
		System.out.println("-----");
		System.out.println(emp2);
	}

	private String name;
	private int age;
	private Address address;
}

【运行结果】:

【运行结果】:

克隆之前:

name:rollen, age:20

Address: state: 中国 munber: 1

克隆之后

name:rollen, age:20

Address: state: 中国 munber: 1

-----

name:hello world, age:100

Address: state: 美国 munber: 2

序列化接口和对象克隆

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Address implements Serializable{
	public Address(){

	}

	public Address(String state, int number){
		this.number = number;
		this.state = state;
	}

	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		sb.append("number: " + number);
		sb.append("state" + state + "\n");
		return sb.toString();
	}

	public String getState(){
		return state;
	}

	public void setState(String state){
		this.state = state;
	}

	public int getNumber(){
		return number;
	}

	public void setNumber(int number){
		this.number = number;
	}

	private String state;
	private int number;
}

public class Employee implements Cloneable, Serializable{
	public Employee(){

	}

	public Employee(String name, int age, Address address){
		this.address = address;
		this.age = age;
		this.name = name;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}

	public int getAge(){
		return age;
	}

	public void setAge(int age){
		this.age = age;
	}

	public Address getAddress(){
		return address;
	}

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

	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		sb.append("name:" + name + ", ");
		sb.append("age:" + age + " \n");
		sb.append("Address: " + address);
		return sb.toString();
	}

	@Override
	protected Employee clone(){
		Employee employee = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try{
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(this);
			oos.close();

			ByteArrayInputStream bais = new ByteArrayInputStream(
					baos.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bais);
			employee = (Employee) ois.readObject();
			ois.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		return employee;
	}

	public static void main(String[] args){
		System.out.println("克隆之前:");
		Address add1 = new Address("中国", 1);
		Employee emp1 = new Employee("rollen", 20, add1);
		System.out.println(emp1);
		System.out.println("克隆之后");
		Employee emp2 = emp1.clone();

		emp2.setName("hello world");
		emp2.setAge(100);
		emp2.address.setNumber(2);
		emp2.address.setState("美国");
		System.out.println(emp1);
		System.out.println("-----");
		System.out.println(emp2);
	}

	private String name;
	private int age;
	private Address address;
}

【运行结果】:

克隆之前:

name:rollen, age:20

Address: number: 1state中国

 

克隆之后

name:rollen, age:20

Address: number: 1state中国

 

-----

name:hello world, age:100

Address: number: 2state美国


 

对于任何一个序列化的对象,都必须要求实现Serializable接口。其次,如果这个类的域中也有引用对象,则也有要求这个引用类型也实现这个接口,。最后,序列化方式实现克隆效率不高,没有直接深度克隆的效率高。有兴趣的朋友 可以测试一下。