博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java(20)---克隆
阅读量:4087 次
发布时间:2019-05-25

本文共 5559 字,大约阅读时间需要 18 分钟。

java支持我们对一个对象进行克隆,那么什么是克隆?

1、什么是克隆?

Java中的克隆分为深克隆和浅克隆

浅克隆:仅仅复制它所考虑的对象,而不复制它所引用的对象。

深克隆:不仅要复制它所考虑的对象,而且还要复制它所引用的对象。

2、为什么要克隆?

引入问题1:为什么要克隆,直接new一个对象不好吗?

new出来的对象,该对象的属性值都是初始化的时候的值。

克隆出来的对象,该对象的属性值可能包含一些已经修改的属性值。

所以,如果需要一个新的对象来保存当前对象的状态的时候,就需要克隆。

引入问题2:既然克隆就是保存当前对象的状态,那么可以将该对象的属性一个一个的复制给new出来的新对象吗?

当然可以,问题是一个个赋值太繁琐。然后效率也不高。而克隆clone是一个native方法,在底层实现的,效率高。

3、如何实现克隆?

在Java中,数据类型分为基本数据类型和引用数据类型

基本数据类型分为:byte, char,  int ,  float ,double ,short , long ,boolean这几种

引用数据类型分为:数组array 、接口interface 、类class等

而深克隆和浅克隆的区别在于:是否支持引用类型的成员变量的复制。

3.1、如何实现浅克隆?

浅克隆一般比较简单,实现步骤如下:

步骤1:被复制的类实现Clonenable接口

步骤2:覆盖clone()方法,方法修饰符为public,在该方法中调用super.clone()方法就可以得到需要复制的对象

代码如下:

1、新建实体类StudenVO,该类需要被克隆,可以实现Cloneable接口

package com.cn.vo;/** * 该实体类需要被克隆,需要实现Cloneable接口 * */public class StudentVO implements Cloneable {	private String stuName;  //学生姓名		/**	 * 覆盖的clone方法,注意此处将 protected改为public	 * */	@Override	public Object clone() throws CloneNotSupportedException {		StudentVO studentVO=null;		try{			//调用super.clone方法进行克隆			studentVO=(StudentVO) super.clone();		}catch(CloneNotSupportedException  e){			e.printStackTrace();		}		return studentVO;	}		//属性get和set方法	public String getStuName() {		return stuName;	}	public void setStuName(String stuName) {		this.stuName = stuName;	}}
2、测试

package com.cn.clone;import com.cn.vo.StudentVO;/** * 浅克隆测试 * */public class Test {	public static void main(String[] args) throws CloneNotSupportedException {		//new方式实例化一个类		StudentVO stu1= new StudentVO();		//为类的属性复制		stu1.setStuName("Tom");		//克隆一个类		StudentVO stu2=(StudentVO) stu1.clone();		System.out.println("学生1"+stu1.getStuName());		System.out.println("学生2"+stu2.getStuName());				//检查这两个对象是否是同一个对象		System.out.println(stu1==stu2);			}	}

结果显示:

结果证明:通过stu1.clone()可以克隆一个对象stu2,stu1和stu2不是同一个对象,即克隆对象和原对象不是同一个对象。

下面我们再做个测试,修改stuName的属性值为Lucy,然后再观察一下 ,代码如下:

package com.cn.clone;import com.cn.vo.ClazzVO;import com.cn.vo.StudentVO;/** * 浅克隆测试 * */public class Test {	public static void main(String[] args) throws CloneNotSupportedException {		//实例化一个班级类		ClazzVO claVO=new ClazzVO();		claVO.setClazzName("六年级一班");				//new方式实例化一个学生类		StudentVO stu1= new StudentVO();		//为类的属性复制		stu1.setStuName("Tom");		stu1.setClaVO(claVO);				//检查这两个对象是否是同一个对象		stu2.setStuName("Lucy");		System.out.println("学生1:"+stu1.getStuName());		System.out.println("学生2:"+stu2.getStuName());	}	}
结果显示:

修改stu2的name不会影响stu1的name,再次证明克隆后的对象与被克隆的对象不是同一个对象

3.2、如何实现深克隆?

深克隆是一个稍微复杂的克隆

1、创建一个学生类StudentVO和一个班级类ClazzVO

package com.cn.vo;/** * 该实体类需要被克隆,需要实现Cloneable接口 * */public class StudentVO implements Cloneable {	private String stuName;  //学生姓名	private ClazzVO claVO; //学生所在班级		/**	 * 覆盖的clone方法,注意此处将 protected改为public	 * */	@Override	public Object clone() throws CloneNotSupportedException {		StudentVO studentVO=null;		try{			//调用super.clone方法进行克隆			studentVO=(StudentVO) super.clone();		}catch(CloneNotSupportedException  e){			e.printStackTrace();		}				return studentVO;	}		//属性get和set方法	public String getStuName() {		return stuName;	}	public void setStuName(String stuName) {		this.stuName = stuName;	}	public ClazzVO getClaVO() {		return claVO;	}	public void setClaVO(ClazzVO claVO) {		this.claVO = claVO;	}	}
package com.cn.vo;/** * 班级实体类 * */public class ClazzVO  {	private String clazzName;  //班级名称	//get和set方法	public String getClazzName() {		return clazzName;	}	public void setClazzName(String clazzName) {		this.clazzName = clazzName;	}}
2、测试

package com.cn.clone;import com.cn.vo.ClazzVO;import com.cn.vo.StudentVO;/** * 浅克隆测试 * */public class Test {	public static void main(String[] args) throws CloneNotSupportedException {		//实例化一个班级类		ClazzVO claVO=new ClazzVO();		claVO.setClazzName("六年级一班");				//new方式实例化一个学生类		StudentVO stu1= new StudentVO();		//为类的属性复制		stu1.setStuName("Tom");		stu1.setClaVO(claVO);				//克隆一个类		StudentVO stu2=(StudentVO) stu1.clone();				System.out.println("学生1:"+stu1.getStuName()+"所属班级:"+stu1.getClaVO().getClazzName());		System.out.println("学生2:"+stu2.getStuName()+"所属班级:"+stu2.getClaVO().getClazzName());	}	}
结果显示:

结果证明:对象确实被克隆成功了

但是还存在一个问题,此时修改stu2的班级属性为五年级三班,再次打印结果

代码如下:

package com.cn.clone;import com.cn.vo.ClazzVO;import com.cn.vo.StudentVO;/** * 浅克隆测试 * */public class Test {	public static void main(String[] args) throws CloneNotSupportedException {		//实例化一个班级类		ClazzVO claVO=new ClazzVO();		claVO.setClazzName("六年级一班");				//new方式实例化一个学生类		StudentVO stu1= new StudentVO();		//为类的属性复制		stu1.setStuName("Tom");		stu1.setClaVO(claVO);				//克隆一个类		StudentVO stu2=(StudentVO) stu1.clone();		claVO.setClazzName("五年级三班");		 		System.out.println("学生1:"+stu1.getStuName()+"所属班级:"+stu1.getClaVO().getClazzName());		System.out.println("学生2:"+stu2.getStuName()+"所属班级:"+stu2.getClaVO().getClazzName());	}	}
结果显示:

结果证明:修改stu2的属性,stu1的属性也会被修改,这样就存在很大的问题

将班级实体类克隆,代码如下:

package com.cn.vo;/** * 班级实体类 * */public class ClazzVO implements Cloneable {	private String clazzName;  //班级名称	//get和set方法	public String getClazzName() {		return clazzName;	}	public void setClazzName(String clazzName) {		this.clazzName = clazzName;	}	@Override	public Object clone() throws CloneNotSupportedException {		ClazzVO clazzVO=null;		try{			clazzVO=(ClazzVO) super.clone();		}catch(Exception e){			e.printStackTrace();		}		return clazzVO;	}		}
在studentVO作如下修改:

@Override	public Object clone() throws CloneNotSupportedException {		StudentVO studentVO=null;		try{			//调用super.clone方法进行克隆			studentVO=(StudentVO) super.clone();		}catch(CloneNotSupportedException  e){			e.printStackTrace();		}		studentVO.claVO=(ClazzVO) claVO.clone();				return studentVO;	}
测试结果如下:

结果证明:修改stu1的引用类型的变量时,不会对克隆对象产生影响

你可能感兴趣的文章
分治算法(一)二分搜索技术
查看>>
分治算法(二)合并排序
查看>>
分治算法(三)快速排序
查看>>
Flutter底部溢出
查看>>
Flutter踩坑之url_launcher
查看>>
跳转到另一个页面之后取消后退按钮
查看>>
flutter踩坑高德地图amap_base
查看>>
flutter极光推送
查看>>
jvm崩溃并输出 hs_err_pidxxxx.log文件异常原因
查看>>
HXAPIGate(中文名:浩心API网关)
查看>>
Nginx搭建TCP反向代理服务
查看>>
netty整合shiro,报There is no session with id [xxxxxx]问题定位及解决
查看>>
Ignite配置
查看>>
Ignite计算网格第一部分
查看>>
将表单序列化之后变成的json格式的数据无法通过Ajax发送到后台的解决
查看>>
使用JAVA代码实现字符串的简单拼接
查看>>
java中的模版方法
查看>>
实现从oss(阿里云)服务器以附件形式下载文件(含批量下载)
查看>>
JSP页面以GET方式传参服务器报400
查看>>
自定义百度地图全局搜索结果的信息窗口
查看>>