JAVA 克隆

1. 拷贝

    在 java 拷贝一个对象 时,引用为同一内存地址,当改变一个对象时会对原来对象也会产生影响

/**
* 对象拷贝
*/
private static void test1() {
		
	Car car =new Car("奔驰", 3.16, "黑色",45.6);
	Car copyCar=car; //简单的对象复制
	System.out.println("复制完成后内容----------------------------------");
	System.out.println(car.getBrand()+"=="+car.getCarLength()+"=="
			+car.getColor()+"=="+car.getPrice());
	System.out.println(copyCar.getBrand()+"=="+copyCar.getCarLength()+"=="
			+copyCar.getColor()+"=="+copyCar.getPrice());
	//改变复制对象的内容
	copyCar.setBrand("奔驰c200");
	copyCar.setPrice(30.5);
		
	System.out.println("修改后内容--------------------------------------");
	System.out.println(car.getBrand()+"=="+car.getCarLength()+"=="
			+car.getColor()+"=="+car.getPrice());
	System.out.println(copyCar.getBrand()+"=="+copyCar.getCarLength()+"=="
			+copyCar.getColor()+"=="+copyCar.getPrice());
}

 

测验结果:

复制完成后内容----------------------------------
奔驰==3.16==黑色==45.6
奔驰==3.16==黑色==45.6
修改后内容--------------------------------------
奔驰c200==3.16==黑色==30.5
奔驰c200==3.16==黑色==30.5

    经上测试后发现拷贝发现两个对象还互相干扰,那怎么可以让两个对象拥有自己独立的状态呢?

2. 浅克隆

    对象克隆后,双方拥有自己独立的状态,修改后不会互相干扰,这种方式叫做克隆,Object中有一个proteced 的Clone方法,通过重写此方法达到浅克隆。

    浅克隆:如果对象的所有属性都属于基本类型或者不可变类,通过浅克隆可以达到双方对象独立。

    实现方式如下代码:

    1.在Car实体类中实现cloneable接口(标记接口),重写clone方法,修改返回类型,调用super.clone(),修改方法的访问修饰符为public(以便在其他类中可以访问);

public class Car implements Cloneable{
	
	private String brand; //汽车品牌
	private double carLength; //汽车车长
	private String color; //汽车颜色
	private double price; //汽车价格


     /*省略getting/setting 和构造方法*/

    /**
     * 重写Object类的克隆方法,实现浅克隆
     */
    @Override
    public Car clone() throws CloneNotSupportedException {
		
	   return (Car)super.clone();
    }
}

    2.测试代码:

    /**
	 * 浅克隆
	 */
	private static void test2() {
		Car car =new Car("奔驰", 3.16, "黑色",45.6);
		
		try {
			Car cloneCar=car.clone(); //通过clone实现克隆
			
			System.out.println("克隆后内容--------------------------------");
			System.out.println(car.getBrand()+"=="+car.getCarLength()+"=="
					  +car.getColor()+"=="+car.getPrice());
			System.out.println(cloneCar.getBrand()+"=="+cloneCar.getCarLength()+"=="
					  +cloneCar.getColor()+"=="+cloneCar.getPrice());
			
			//修改克隆数据内容
			cloneCar.setBrand("奔驰c200");
			cloneCar.setCarLength(2.89);
			
			System.out.println("修改后结果---------------------------------");
			System.out.println(car.getBrand()+"=="+car.getCarLength()+"=="
					  +car.getColor()+"=="+car.getPrice());
			System.out.println(cloneCar.getBrand()+"=="+cloneCar.getCarLength()+"=="
					  +cloneCar.getColor()+"=="+cloneCar.getPrice());
			
		} catch (CloneNotSupportedException e) {
			System.out.print("对象克隆出现异常,异常信息:");
			e.printStackTrace();
		}
		
	}

  测试结果:

克隆后内容--------------------------------
奔驰   ==    3.16   ==     黑色    ==   45.6
奔驰   ==    3.16   ==     黑色    ==   45.6
修改后结果---------------------------------
奔驰           ==    3.16   ==      黑色    ==  45.6
奔驰c200    ==    2.89   ==      黑色    ==  45.6

    3.浅克隆图例:

    

    从上图可以看出浅克隆会复制所有数据一份,从新生成一个对象,双方拥有独立的空间,修改不会干扰,但是引用类型String ,复制的却是地址,改变会修改原数据吗?答案是不会,因为String 类型属于不可变类型(用final 修饰),内容改变后会重新开辟内存空间,指向新的引用。但是自己创建的类呢???

3.深克隆

    给Car 类增加 private Date date; //出厂日期 属性,在Test 类中 调用 date.setTime(),修改内容,发现两个数据对象都修改啦,这是因为复制的只是地址,我们现在通过深克隆,达到互不干扰的效果。

    1.添加对Date 的克隆

    /**
	 * 重写Object类的克隆方法,实现浅克隆
	 */
	@Override
	public Car clone() throws CloneNotSupportedException {
		
		Car car = (Car)super.clone();
		
		//增加Date 类型的深克隆
		
		car.date =(Date)date.clone();  //Date 类中默认重写了clone方法
		
		return car;
	}

     2.调试Debug后发现克隆后Date 的引入地址不一样啦

    

    3.对自定义类的克隆

        对自定义类实现Cloneable,重写clone方法,重复以上步骤

    如果类引用多层的话,每次都重写类的clone方法,会很累,下来我们就用 java 序列化实现深克隆  

4. JAVA 序列化 -- 深克隆

    1. 克隆的类要实现 Serializable 接口(标记接口),类有引用的自定义类也要实现此接口。重写clone方法、

    

/**
 * 员工信息类
 * @author john
 *
 */
public class Employee implements Serializable {
	
	
	/**
	 * 序列化id
	 */
	private static final long serialVersionUID = 1L;
	
	
	private String name; //员工姓名
	private int age; //员工年龄
	private Dept dept; //员工部门
	private Date date; //入职时间

    /*省略getting/setting 和构造方法*/

	/**
	 * java 序列化实现深克隆
	 */
	@Override
	public Employee clone(){
		Employee emp=null;
		//对象序列化
		ByteArrayOutputStream out=new ByteArrayOutputStream();
		
		try {
			ObjectOutputStream outStream=new ObjectOutputStream(out);
			outStream.writeObject(this);
			
			//反序列化
			ByteArrayInputStream inp=new ByteArrayInputStream(out.toByteArray());
			ObjectInputStream inputStream=new ObjectInputStream(inp);
			emp=(Employee)inputStream.readObject();
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		return emp;
	}
}

    2.测试代码

    /**
	 *  Java 序列化实现深克隆 
	 */
	private static void test4() {
		Dept dept=new Dept("001", "营销部", new Date());
		
		Employee emp=new Employee("张三", 20, dept, new Date());
		
		Employee cloneEmp=emp.clone();
		
		System.out.println("克隆后内容---------------------------------");
		System.out.println(emp.getName()+"=="+emp.getAge()+"=="+emp.getDate()
				+"=="+emp.getDept().getId()+"=="+emp.getDept().getDeptName()+"=="+emp.getDept().getDate());
		System.out.println(cloneEmp.getName()+"=="+cloneEmp.getAge()+"=="+cloneEmp.getDate()
				+"=="+cloneEmp.getDept().getId()+"=="+cloneEmp.getDept().getDeptName()+"=="+cloneEmp.getDept().getDate());
		
		//修改克隆对象内容
		cloneEmp.setAge(30);
		cloneEmp.setName("李四");
		cloneEmp.getDate().setTime(new GregorianCalendar(2016,8,9).getTimeInMillis());
		cloneEmp.getDept().setDeptName("开发部");
		cloneEmp.getDept().getDate().setTime(new GregorianCalendar(2015,8,9).getTimeInMillis());
		
		System.out.println("修改后内容---------------------------------");
		System.out.println(emp.getName()+"=="+emp.getAge()+"=="+emp.getDate()
				+"=="+emp.getDept().getId()+"=="+emp.getDept().getDeptName()+"=="+emp.getDept().getDate());
		System.out.println(cloneEmp.getName()+"=="+cloneEmp.getAge()+"=="+cloneEmp.getDate()
				+"=="+cloneEmp.getDept().getId()+"=="+cloneEmp.getDept().getDeptName()+"=="+cloneEmp.getDept().getDate());
		
	}

3.测试结果

克隆后内容---------------------------------
张三==20==Wed Apr 26 15:13:23 CST 2017==001==营销部==Wed Apr 26 15:13:19 CST 2017
张三==20==Wed Apr 26 15:13:23 CST 2017==001==营销部==Wed Apr 26 15:13:19 CST 2017
修改后内容---------------------------------
张三==20==Wed Apr 26 15:13:23 CST 2017==001==营销部==Wed Apr 26 15:13:19 CST 2017
李四==30==Fri Sep 09 00:00:00 CST 2016==001==开发部==Wed Sep 09 00:00:00 CST 2015

4.debug 下

     

    至此,Java克隆完成!

github代码地址:https://github.com/kedouC/exampleClone.git

转载于:https://my.oschina.net/u/3402916/blog/887589

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值