文档章节

Java深、浅克隆(clone)

H
 Henrykin
发布于 2016/11/04 16:18
字数 625
阅读 45
收藏 0

    Java的基类Object中有个本地方法clone(),由于该方法是protected访问权限,所以只能在Object内部或其子类内部访问,可是不能在类外通过对象.clone()访问。

 protected native Object clone() throws CloneNotSupportedException;

    自定义的类需要实现"克隆",一定要实现Cloneable接口(该接口内没有任何方法,但如果不实现该接口就直接在类里调用Object的clone(),运行报错)。

    1、浅拷贝:

    需要实现拷贝的自定义User类

public class User implements Cloneable{
		private int id;
		private String name;

		public User(int id, String name) {
			this.id = id;
			this.name = name;
		}

		@Override //这个注解有和没有都一样
		public User clone() throws CloneNotSupportedException {
			return (User)super.clone();//直接调用Object的clone(),并返回就可以了
		}
		
		public int getId() {
			return id;
		}
		
		public String getName() {
			return name;
		}
		
	}

    测试类:

public class TestClone {
	
	public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
		User u1 = new User(1, "zhangsan");
		User u2 = u1.clone();
		System.out.println(u1==u2);
		System.out.println(u1.getId()==u2.getId());
		System.out.println(u1.getName()==u2.getName());
	}
}

    结果:false、true、true

    可能很多人会觉得第三个应该是false。我们先来看一下Object类提供的拷贝机制,就会明白了。

    Object类提供的Clone机制只对对象里的各实例变量进行“简单复制”,如果实例变量的类型是引用类型(本例中的String name),也只是简单得复制这个引用变量(应该是这样:u2=u1),这样u1和u2仍然指向内存中的同一实例。如果需要引用类型的实例也拷贝一份,那就需要深拷贝了。

    2、深拷贝:    

    需要拷贝的User类还要实现 Serializable接口(也是没有任何方法的接口),因为要用到输入、输出流将对象实例从内存中复制一份。

    User类:

public class User implements Cloneable,Serializable{
		private int id;
		private String name;
		
		@Override
		public User clone() throws CloneNotSupportedException {
		    ByteArrayOutputStream baos = new ByteArrayOutputStream();//字节输出流
			ObjectOutputStream out = new ObjectOutputStream(baos);//对象输出流中嵌套封装字节输出流
			
			out.writeObject(this);//将调用clone()当前对象的数据输出保存在字节输出流中
			
			ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());//字节输入流,指定读取的数据来自baos中的字节
			ObjectInputStream in = new ObjectInputStream(bais);//对象输入流封装字节输入流
			
			User u = (User)in.readObject();//将数据以对象的形式读取
			return u;
		}
		
		public User(int id, String name) {
			super();
			this.id = id;
			this.name = name;
		}
		
		public int getId() {
			return id;
		}

		public String getName() {
			return name;
		}

	}

    测试类还是和上面的测试类一样,结果为:false,true,false

通过下图便可了解深拷贝的机制:

 

© 著作权归作者所有

H
粉丝 4
博文 102
码字总数 12788
作品 0
广州
私信 提问
Java拾遗:008 - 对象克隆与浅拷贝、深拷贝

对象克隆 Object类中有一个方法叫,完整代码 首先它是一个Native方法,而且是受保护的(),抛出一个异常(JDK1.8)。 通常程序员自己定义的类不能直接调用方法,如果要在外部调用,需要重写...

一别丶经年
2018/08/04
59
0
Java中如何克隆集合——ArrayList和HashSet深拷贝

编程人员经常误用各个集合类提供的拷贝构造函数作为克隆List,Set,ArrayList,HashSet或者其他集合实现的方法。需要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味着存...

LCZ777
2014/04/14
89
0
Java中的克隆Cloneable

浅克隆与深克隆 当拷贝一个变量时,原始变量与拷贝变量引用了同一个对象。那么当改变一个变量所引用的对象时,就会对另一个变量产生影响。形象化一点说,就像某人A有一把遥控,用来控制电视,...

静水楼台
2013/06/04
219
0
深入理解原型模式 ——通过复制生成实例

Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_Guide一 原型模式介绍 在面向对象系统中,使用原型模式来复制一个对象自...

Amsour丶
2018/06/19
0
0
深浅克隆面试题汇总——附详细答案

在开始学习深克隆和浅克隆之前,我们先来看下面代码,有什么问题? 程序执行结果: 可以看出,如果使用等号复制时,对于值类型来说,彼此之间的修改操作是相对独立的,而对于引用类型来说,因...

王磊的博客
09/18
9
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS 7系统增加swap

转载请注明文章出处:CentOS 7系统增加swap swap是位于磁盘上的特殊文件(或分区),属于“虚拟内存”的一部分。通俗点就是内存的备胎,内存充足的情况下,基本上没swap什么事(和设置有关)...

tlanyan
35分钟前
5
0
基于Prometheus和Grafana的监控平台 - 环境搭建

相关概念 微服务中的监控分根据作用领域分为三大类,Logging,Tracing,Metrics。 Logging - 用于记录离散的事件。例如,应用程序的调试信息或错误信息。它是我们诊断问题的依据。比如我们说...

JAVA日知录
今天
5
0
PHP运行时全局构造体

struct _php_core_globals { zend_bool magic_quotes_gpc; // 是否对输入的GET/POST/Cookie数据使用自动字符串转义。 zend_bool magic_quotes_runtime; //是否对运行时从外部资源产生的数据使...

冻结not
今天
4
0
webpack插件html-webpack-plugin

本文转载于:专业的前端网站→webpack插件html-webpack-plugin 1、插件安装 npm install html-webpack-plugin --save-dev 2、插件使用 webpack.config.js配置文件为: var htmlWebpackPlugin=...

前端老手
今天
6
0
数据挖掘

zhengchen1996
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部