Java clone() 方法克隆对象——深拷贝与浅拷贝
基本数据类型引用数据类型特点
1、基本数据类型的特点:直接存储在栈(stack)中的数据
2、引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
深拷贝与浅拷贝特点
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
当把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。
Java clone方法深拷贝与浅拷贝
clone浅拷贝
由CloneDemo类可以看出,没有重写clone方法,对象中的引用数据类型只是复制了该引用数据类型的引用,并没有在内存空间中开辟空间复制该引用数据类型,即对该引用数据类型进行了浅拷贝而不是深拷贝。
package JDKSource.lang;
public class CloneDemo implements Cloneable {
private int num;
private String name;
private Helper helper;
public CloneDemo() {
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Helper getHelper() {
return helper;
}
@Override
public String toString() {
return "CloneDemo{" +
"num=" + num +
", name='" + name + '\'' +
", helper=" + helper +
'}';
}
public void setHelper(Helper helper) {
this.helper = helper;
}
public static class Helper {
public int num;
public Helper(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public String toString() {
return "Helper{" +
"num=" + num +
'}';
}
}
public static void main(String[] args) throws CloneNotSupportedException {
CloneDemo d1 = new CloneDemo();
d1.setName("Jack");
d1.setNum(10);
d1.setHelper(new Helper(100));
CloneDemo d2 = (CloneDemo) d1.clone();
System.out.println(d1.name == d2.name);
System.out.println(d1.num == d2.num);
System.out.println(d1.helper == d2.helper);
d2.setNum(11);
d2.setName("json");
d2.getHelper().setNum(101);
System.out.println(d1.name);
System.out.println(d1.num);
System.out.println(d1.helper.toString());
System.out.println(d2.name);
System.out.println(d2.num);
System.out.println(d2.helper.toString());
/* Output:
true
true
true
Jack
10
Helper{num=101}
json
11
Helper{num=101}*/
}
}
clone深拷贝
对Helper类和CloneDemo都重写clone方法:
CloneDemo重写clone方法:
@Override
protected CloneDemo clone() throws CloneNotSupportedException {
CloneDemo clone = (CloneDemo1) super.clone();
clone.helper = helper.clone();
return clone;
}
Helper重写clone方法:
@Override
protected Helper clone() throws CloneNotSupportedException {
Helper helper = null;
Helper clone = (Helper) super.clone();
return clone;
}
输出结果:
结果显示,对Helper类和CloneDemo都重写clone方法后,实现了对引用数据类型Helper的深拷贝。
/* Output:
true
true
false
Jack
10
Helper{num=100}
json
11
Helper{num=101}*/
完整代码:
package JDKSource.lang;
public class CloneDemo1 implements Cloneable {
private int num;
private String name;
private Helper helper;
public CloneDemo1() {
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Helper getHelper() {
return helper;
}
@Override
protected CloneDemo1 clone() throws CloneNotSupportedException {
CloneDemo1 clone = (CloneDemo1) super.clone();
clone.helper = helper.clone();
return clone;
}
@Override
public String toString() {
return "CloneDemo{" +
"num=" + num +
", name='" + name + '\'' +
", helper=" + helper +
'}';
}
public void setHelper(Helper helper) {
this.helper = helper;
}
public static class Helper implements Cloneable {
public int num;
public Helper(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public String toString() {
return "Helper{" +
"num=" + num +
'}';
}
@Override
protected Helper clone() throws CloneNotSupportedException {
Helper helper = null;
Helper clone = (Helper) super.clone();
return clone;
}
}
public static void main(String[] args) throws CloneNotSupportedException {
CloneDemo1 d1 = new CloneDemo1();
d1.setName("Jack");
d1.setNum(10);
d1.setHelper(new Helper(100));
CloneDemo1 d2 = (CloneDemo1) d1.clone();
System.out.println(d1.name == d2.name);
System.out.println(d1.num == d2.num);
System.out.println(d1.helper == d2.helper);
d2.setNum(11);
d2.setName("json");
d2.getHelper().setNum(101);
System.out.println(d1.name);
System.out.println(d1.num);
System.out.println(d1.helper.toString());
System.out.println(d2.name);
System.out.println(d2.num);
System.out.println(d2.helper.toString());
/* Output:
true
true
false
Jack
10
Helper{num=100}
json
11
Helper{num=101}*/
}
}
Java clone() 方法克隆对象——深拷贝与浅拷贝的更多相关文章
- Java 中如何使用clone()方法克隆对象?
java为什么要 对象克隆: 在程序开发时,有时可能会遇到以下情况:已经存在一个对象A,现在需要一个与A对象完全相同的B 对象,并对B 对象的属性值进行修改,但是A 对象原有的属性值不能改变.这时,如 ...
- java对象的克隆以及深拷贝与浅拷贝
一.为什么要使用克隆 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也 ...
- 关于Java的Object.clone()方法与对象的深浅拷贝
文章同步更新在个人博客:关于Java的Object.clone()方法与对象的深浅拷贝 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Object.clon ...
- Object.clone()方法与对象的深浅拷贝
转载:[https://www.cnblogs.com/nickhan/p/8569329.html] 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Obj ...
- javascript对象深拷贝,浅拷贝 ,支持数组
javascript对象深拷贝,浅拷贝 ,支持数组 经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One meth ...
- Java clone方法(下)
1.终于调用的是一个JNI方法,即java本地方法,加高速度 2.使用clone方法,分为浅复制.深复制,这里直接使用网上抄来的案例来说明吧: 说明: 1)为什么我们在派生类中覆盖Object的clo ...
- java对象克隆以及深拷贝和浅拷贝
1.什么是"克隆"? 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不 ...
- JAVA中对象的克隆及深拷贝和浅拷贝
使用场景: 在日常的编程过程 中,经常会遇到,有一个对象OA,在某一时间点OA中已经包含了一些有效值 ,此时可能会需一个和OA完全相对的新对象OB,并且要在后面的操作中对OB的任何改动都不会影响到OA ...
- java克隆之深拷贝与浅拷贝
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java深拷贝与浅拷贝实际项目中用的不多,但是对于理解Java中值传递,引用传递十分重要,同时个人认为对于理解内存模型也有帮助,况且面试中也是经常问 ...
随机推荐
- LeetCode通关:数组十七连,真是不简单
分门别类刷算法,坚持,进步! 刷题路线参考:https://github.com/chefyuan/algorithm-base https://github.com/youngyangy ...
- Mybatis学习笔记-ResultMap结果集映射
解决属性名与字段名不一致的问题 新建项目 --> 测试实体类字段不一致的情况 数据库字段:id,name,pwd 实体类属性:id,name,password 输出结果 User{id=1, n ...
- AndroidStudio 插件总结
工作中常用的插件备注如下: Alibaba Java Coding GuidelinesCheckStyle-IDEAAndroid Drawable PreviewGsonFormatTransla ...
- WPF DataGrid DataGridTextColumn
Style设置时,无法绑定到数据,需要这样写 1 <DataGridTextColumn Header="呵呵" Binding="{Binding ID}&quo ...
- JS基础-数据类型判断typeof、instanceof、Object.prototype.toString
typeof用在基本数据类型和函数时,返回其对应类型的描述,对于引用类型都返回为object. instanceof无法判断基本数据类型,对于引用类型数据,返回其其对应类型. Object.proto ...
- Oracle数据泵导入的时候创建索引是否会使用并行?
一.疑问,Oracle数据泵导入的时候创建索引是否会使用并行? 某客户需要使用数据泵进行迁移,客户咨询导入的时间能不能加快一点. 那么如何加快导入的速度呢? 多加一些并行,那么创建索引内部的索引并行度 ...
- 身边好几个技术一般的程序员都面上了,阿里P7门槛降低?
经常在网上的论坛里看到讨论程序员的级别,尤其在跳槽类的信息里可以看到对标阿里P7,百度T6,腾讯3.1等字眼,似乎大厂的级别俨然可以成为业内的通用货币,类似于高考分数一样,哪一档就对应着什么样的待遇. ...
- Android 已发行多年,移动 App 已经趋近饱和,那么 Android 开发还会有那么吃香吗?
一.关于Android的前景 不断地也听见很多人在谈做Android是否还有前途.Android研发在走下坡路了.Android的工作太难找了.Android是不是已经凉了...... 对于这些其实我 ...
- 2020互联网寒冬之下,作为一个Android老码农,是如何进入腾讯的?
由于众所周知的原因,原生Android开发如今已经日渐凋敝,作为一个Android程序员,不仅要会Java,Kotlin,JavaScript,Css,Html,还要会Flutter,C++,FFmp ...
- The Apache Tomcat Native library which allows using OpenSSL was not found on the java.library.path 问题解决记录
1.问题 启动Tomcat之后,在浏览器输入IP后显示503,查看catalina.log发现报错: 2.问题定位:缺少 tomcat-native library 就是说 缺少Tomcat Nati ...