是时候捋一捋 Java 的深浅拷贝了

在开发、刷题、面试中,我们可能会遇到将一个对象的属性赋值到另一个对象的情况,这种情况就叫做拷贝。拷贝与Java内存结构息息相关,搞懂Java深浅拷贝是很必要的!

在对象的拷贝中,很多初学者可能搞不清到底是拷贝了引用还是拷贝了对象。在拷贝中这里就分为引用拷贝、浅拷贝、深拷贝进行讲述。

引用拷贝

引用拷贝会生成一个新的对象引用地址,但是两个最终指向依然是同一个对象。如何更好的理解引用拷贝呢?很简单,就拿我们人来说,通常有个姓名,但是不同场合、人物对我们的叫法可能不同,但我们很清楚哪些名称都是属于"我"的!

当然,通过一个代码远程桌面示例让大家领略一下(为了简便就不写get、set等方法):

class Son {

String name;

int age;

public Son(String name, int age) {

this.name = name;

this.age = age;

}

}public class test {

public static void main(String[] args) {

Son s1 = new Son("son1", 12);

Son s2 = s1;

s1.age = 22;

System.out.println(s1);

System.out.println(s2);

System.out.println("s1的age:" + s1.age);

System.out.println("s2的age:" + s2.age);

System.out.println("s1==s2" + (s1 == s2));//相等

}

}

输出的结果为:

Son@135fbaa4

Son@135fbaa4

s1的age:22

s2的age:22true

浅拷贝

如何创建一个对象,将目标对象的内容复制过来而不是直接拷贝引用呢?

这里先讲一下浅拷贝,浅拷贝会创建一个新对象,新对象和原对象本身没有任何关系,新对象和原对象不等,但是新对象的属性和老对象相同。具体可以看如下区别:

如果属性是基本类型(int,double,long,boolean等),拷贝的就是基本类型的值;

如果属性是引用类型,拷贝的就是内存地址(即复制引用但不复制引用的对象) ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。

如果用一张图来描述一下浅拷贝,

如何实现浅拷贝呢?也很简单,就是在需要拷贝的类上实现Cloneable接口并重写其clone()方法。

@Overrideprotected Object clone() throws CloneNotSupportedException {

return super.clone();

}

在使用的时候直接调用类的clone()方法即可。具体案例如下:

class Father{

String name;

public Father(String name) {

this.name=name;

}

@Override

public String toString() {

return "Father{" +

"name='" + name + '\'' +

'}';

}

}class Son implements Cloneable {

int age;

String name;

Father father;

public Son(String name,int age) {

this.age=age;

this.name = name;

}

public Son(String name,int age, Father father) {

this.age=age;

this.name = name;

this.father = father;

}

@Override

public String toString() {

return "Son{" +

"age=" + age +

", name='" + name + '\'' +

", father=" + father +

'}';

}

@Override

protected Son clone() throws CloneNotSupportedException {

return (Son) super.clone();

}

}public class test {

public static void main(String[] args) throws CloneNotSupportedException {

Father f=new Father("bigFather");

Son s1 = new Son("son1",13);

s1.father=f;

Son s2 = s1.clone();

System.out.println(s1);

System.out.println(s2);

System.out.println("s1==s2:"+(s1 == s2));//不相等

System.out.println("s1.name==s2.name:"+(s1.name == s2.name));//相等

System.out.println();

//但是他们的Father father 和String name的引用一样

s1.age=12;

s1.father.name="smallFather";//s1.father引用未变

s1.name="son222";//类似 s1.name=new String("son222") 引用发生变化

System.out.println("s1.Father==s2.Father:"+(s1.father == s2.father));//相等

System.out.println("s1.name==s2.name:"+(s1.name == s2.name));//不相等

System.out.println(s1);

System.out.println(s2);

}

}

运行结果为:

Son{age=13, name='son1', father=Father{name='bigFather'}}

Son{age=13, name='son1', father=Father{name='bigFather'}}

s1==s2:false

s1.name==s2.name:true//此时相等

s1.Father==s2.Father:true

s1.name==s2.name:false//修改引用后不等

Son{age=12, name='son222', father=Father{name='smallFather'}}

Son{age=13, name='son1', father=Father{name='smallFather'}}

不出意外,这种浅拷贝除了对象本身不同以外,各个零部件和关系和拷贝对象都是相同的,就好像双胞胎一样,是两个人,但是其开始的样貌、各种关系(父母亲人)都是相同的。需要注意的是其中name初始==是相等的,是因为初始浅拷贝它们指向一个相同的String,而后s1.name="son222" 则改变引用指向。

(0)

相关推荐

  • 为什么重写equals方法,还必须要重写hashcode方法

    原因: 1.为了提高效率. 采取重写hashcode方法,先进行hashcode比较,如果不同,那么就没必要在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大 ...

  • Java中this关键字的使用

    一,表示类中属性 1,没有使用this的情况   class Person{ // 定义Person类 private String name ; // 姓名 private int age ; // ...

  • java json格式化的两种方式

    Gson 创建演示所用类 class Person{ private String name; private int age; public Person() {} //java fhadmin.c ...

  • 一些JavaSE学习过程中的思路整理(一)(主观性强,持续更新中...)

    目录 一些JavaSE学习过程中的思路整理(一)(主观性强,持续更新中...) Java书写规范 IDEA的一些常用快捷键 Java类中作为成员变量的类 Java源文件中只能有一个public类 Ja ...

  • 23种设计模式之原型模式

    原型模式 1.基本介绍 1)原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并通过拷贝这些原型,创建新的对象. 2)原型模式是一种创建型设计模式,允许一个对象再创建另一个可定制的 ...

  • 来一起捋一捋机器学习分类算法

    来自:算法与数学之美 可是,你能够如数家珍地说出所有常用的分类算法,以及他们的特征.优缺点吗?比如说,你可以快速地回答下面的问题么: KNN算法的优缺点是什么? Naive Bayes算法的基本假设是 ...

  • $复星医药(SH600196)$ 我们来捋一捋复星这波是不是确定能冲高,还是现在已经是高位了。 复星...

    复星A股这波底部启动放量大涨的第一天是4.8号,接下去是老套路下跌几日,让散户以为跟原来一样拉高然后阴跌出货,到了16号以后,消息面的影响以及季报的即将来临,让主力(这里把所有大资金简称为主力了,包括 ...

  • 捋一捋那些能“排结石”的秘验方

    捋一捋那些能“排结石”的秘验方

  • 带你捋一捋天问一号所涉考点

    过去的一年我们国家的北斗三号全球组网系统建设完成;天问一号火星探测器发射成功;嫦娥五号月面采样返回--篇幅所限我们没有办法一一展开,今天就来重点研究一下身负重任去探索火星生命的天问一号吧. 天问一号是 ...

  • 来!一起捋一捋机器学习分类算法

    来源 : 大数据文摘出品 说起分类算法,相信学过机器学习的同学都能侃上一二. 可是,你能够如数家珍地说出所有常用的分类算法,以及他们的特征.优缺点吗?比如说,你可以快速地回答下面的问题么: KNN算法 ...

  • 精彩!煤里来,土里去,捋一捋整条化工产业链。。。

    法律顾问:赵建英律师 作者:韩冰冰.徐东 来源:信达期货 在开始具体介绍之前,首先讲一下关于方法论的知识,如何按照一个固定的体系了解复杂的化工产业链.在唯心主义哲学中,有三个终极问题: "你 ...

  • ​户口迁移到城镇,土地承包能否延期30年?捋一捋答案就清晰了

    户口迁移到城镇,土地承包能否延期30年?捋一捋答案就清晰了 土地历来都是农民的命根子,失去了土地,对于农民来说就基本保障都没有了,不过国家政策的进一步放开,有劳动能力的人口不断的向城市涌进,进城上班和 ...

  • 收藏 | 一起捋一捋机器学习分类算法

    仅做学术分享,如有侵权,联系删除 转载于 :大数据文摘出品 来源:builtin 编译:邢畅.刘兆娜.李雷.钱天培 说起分类算法,相信学过机器学习的同学都能侃上一二. 可是,你能够如数家珍地说出所有常 ...

  • 觉得不对劲?别着急,坐下来捋一捋

    如果工作中看到了一些反常的操作,你觉得不对劲,八成就真的不对劲了. 事出反常必有妖. 平常运转正常的项目,忽然开始被各种挑刺. 本来符合要求的产品,忽然被嫌弃不够完美. 能够正常沟通的人,忽然开始问一 ...