【Java SE基础】如何理解clone对象?

目录

1.为什么要用clone?

2.new一个对象的过程和clone一个对象的过程的区别

3.clone对象的使用

复制对象和复制引用的区别


1.为什么要用clone?

在我们实际编程的过程当中,常常会遇到这样的情况:目前有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同的新对象B,并且此后对B的任何改动都不会影响到A的值,换句话说,A和B是两个独立的对象,但是B的初始值是由A对象来确定的。在Java语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然由很多途径,但是实现clone()方法是其中最简单,也是最高效的。

2.new一个对象的过程和clone一个对象的过程的区别

首先来说一下new操作符,它的本意就是分配内存。程序在执行到new操作符的时候,首先会去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,来填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象就创建完毕了,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用来操作这个对象了。

而clone在第一步和new是相似的,也是先分配内存,在调用clone()方法时,分配的内存和原对象(即调用clone方法的对象)相同,然后再使用原对象中对应的各个域,来填充新对象的域,填充完成之后,clone()方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。

3.clone对象的使用

复制对象和复制引用的区别

首先来看以下这段代码:

1. Person p = new Person(23, "zhang");
2. Person p1 = p; 
3. System.out.println(p);
4. System.out.println(p1);

这里会有一个疑问:当Person p1 = p; 执行之后,是创建了一个新的对象吗?

对于这个问题,我们先来看一下打印结果:

com.cto.Person@2f9ee1ac
com.cto.Person@2f9ee1ac

从打印结果可以看出,打印的地址值是相同的,既然地址是相同的,那么他们肯定是同一个对象。p和p1只是引用而已,他们都指向了一个相同的对象Person(23,"zhang")。我们可以把这种现象叫做引用的复制。在上述代码执行完成之后,内存中的情景如下图所示:

而下面这段代码则是真真正正地克隆了一个对象:

Person p = new Person(23, "zhang");  
Person p1 = (Person) p.clone();   
System.out.println(p);  
System.out.println(p1);

当然我们还是先来看一下打印结果:

com.cto.Person@2f9ee1ac
com.cto.Person@67f1fba0

从打印结果可以看出,两个对象的地址是不同的,也就是说创建了新的对象,而不是把原对象的地址赋给了一个新的引用变量。

在上述代码执行完成之后,内存中的情景如下图所示:

这里给大家补充一个软考的小考点:

程序运行时的用户内存空间一般划分为:代码区、静态数据区、栈区堆区。其中栈区和堆区也称为动态数据区。

  • 程序的二进制指令,即编译后的机器代码,存储在代码区;

  • 全局变量与静态变量的存储空间在静态数据区;

  • 局部变量、函数参数、返回地址等存放在栈区,且栈的分配和回收是自动的;(基本类型、引用类型变量和方法在栈空间分配)

  • 堆用于存储动态分配的变量,如结构体、数组等,与栈不同,其内存分配和回收需要程序员手动处理。(对象在堆空间分配)

下一篇文章会为大家讲解一下深拷贝与浅拷贝的相关内容~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值