一、拷贝的引入


(1)、引用拷贝

创建一个指向对象的引用变量的拷贝。

Teacher teacher = new Teacher("Taylor",26);
Teacher otherteacher = teacher;
System.out.println(teacher);
System.out.println(otherteacher);

输出结果:

blog.Teacher@355da254
blog.Teacher@355da254

结果分析:由输出结果可以看出,它们的地址值是相同的,那么它们肯定是同一个对象。teacher和otherteacher的只是引用而已,他们都指向了一个相同的对象Teacher(“Taylor”,26)。这就叫做引用拷贝。

(2)、对象拷贝

创建对象本身的一个副本。

Teacher teacher = new Teacher("Swift",26);
Teacher otherteacher = (Teacher)teacher.clone();
System.out.println(teacher);
System.out.println(otherteacher);

输出结果:

blog.Teacher@355da254
blog.Teacher@4dc63996

注:深拷贝和浅拷贝都是对象拷贝

二、浅拷贝


(1)、定义

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象

(2)、浅拷贝实例

package com.test;

public class ShallowCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher();
teacher.setName("riemann");
teacher.setAge(27); Student2 student1 = new Student2();
student1.setName("edgar");
student1.setAge(18);
student1.setTeacher(teacher); Student2 student2 = (Student2) student1.clone();
System.out.println("拷贝后");
System.out.println(student2.getName());
System.out.println(student2.getAge());
System.out.println(student2.getTeacher().getName());
System.out.println(student2.getTeacher().getAge()); System.out.println("修改老师的信息后-------------");
// 修改老师的信息
teacher.setName("Games");
System.out.println(student1.getTeacher().getName());
System.out.println(student2.getTeacher().getName()); }
} class Teacher implements Cloneable {
private String name;
private int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
}
} class Student2 implements Cloneable {
private String name;
private int age;
private Teacher teacher; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public Teacher getTeacher() {
return teacher;
} public void setTeacher(Teacher teacher) {
this.teacher = teacher;
} public Object clone() throws CloneNotSupportedException {
Object object = super.clone();
return object;
}
}

输出结果:

拷贝后
edgar
18
riemann
27
修改老师的信息后-------------
Games
Games

结果分析:两个引用student1和student2指向不同的两个对象,但是两个引用student1和student2中的两个teacher引用指向的是同一个对象,所以说明是浅拷贝。

三、深拷贝


(1)、定义

深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

(2)、深拷贝实例

package com.test;

public class DeepCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher2 teacher = new Teacher2();
teacher.setName("riemann");
teacher.setAge(27); Student3 student1 = new Student3();
student1.setName("edgar");
student1.setAge(18);
student1.setTeacher(teacher); Student3 student2 = (Student3) student1.clone();
System.out.println("拷贝后");
System.out.println(student2.getName());
System.out.println(student2.getAge());
System.out.println(student2.getTeacher().getName());
System.out.println(student2.getTeacher().getAge()); System.out.println("修改老师的信息后-------------");
// 修改老师的信息
teacher.setName("Games");
System.out.println(student1.getTeacher().getName());
System.out.println(student2.getTeacher().getName());
}
} class Teacher2 implements Cloneable {
private String name;
private int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public Object clone() throws CloneNotSupportedException {
return super.clone();
}
} class Student3 implements Cloneable {
private String name;
private int age;
private Teacher2 teacher; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public Teacher2 getTeacher() {
return teacher;
} public void setTeacher(Teacher2 teacher) {
this.teacher = teacher;
} public Object clone() throws CloneNotSupportedException {
// 浅复制时:
// Object object = super.clone();
// return object; // 改为深复制:
Student3 student = (Student3) super.clone();
// 本来是浅复制,现在将Teacher对象复制一份并重新set进来
student.setTeacher((Teacher2) student.getTeacher().clone());
return student; }
}

输出结果:

拷贝后
edgar
18
riemann
27
修改老师的信息后-------------
Games
riemann

结果分析:

两个引用student1和student2指向不同的两个对象,两个引用student1和student2中的两个teacher引用指向的是两个对象,但对teacher对象的修改只能影响student1对象,所以说是深拷贝。

关于Java深拷贝和浅拷贝区别,你学废了么?

  • 区别:如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用类型数据只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用类型数据进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。

问:clone()方法,是对当前对象进行浅拷贝,引用类型依然是在传递引用,那么,如何进行一个深拷贝呢?

  • 序列化这个对象,再反序列化回来,就可得到这个新的对象,无非就是序列化的规则需要自己来写。
  • 继续利用clone()方法,既然clone()方法是我们来重写的,实际上可以对其内的引用类型的变量,在进行一次clone()。

Java的深拷贝和浅拷贝的区别的更多相关文章

  1. java基础——深拷贝和浅拷贝的区别

    浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝. 深拷贝:对基本数据类型进行值传递,对引用数据类型船舰一个新的对象,并复制内容,这是深拷贝.

  2. Java的深拷贝和浅拷贝

    关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用 ...

  3. Python 深拷贝和浅拷贝的区别

    python的复制,深拷贝和浅拷贝的区别    在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用  ...

  4. 细说 Java 的深拷贝和浅拷贝

    版权声明: 本账号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影所有. 未经允许,不得转载. 一.前言 任何变成语言中,其实都有浅拷贝和深拷贝的概念,Java 中也不例外.在对一个现 ...

  5. Python赋值语句与深拷贝、浅拷贝的区别

    参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...

  6. python深拷贝和浅拷贝的区别

    首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别. 什么是可变对象,什么是不可变对象: 可变对象 ...

  7. c# 深拷贝与浅拷贝的区别分析及实例

    浅拷贝(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用. 深拷贝(深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.就是说完全是新对象产生的. 深拷贝是指源对象与拷贝对象互相独 ...

  8. python深拷贝与浅拷贝的区别

    可变对象:一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值 不可变对象:一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象 ...

  9. 【python测试开发栈】—理解python深拷贝与浅拷贝的区别

    内存的浅拷贝和深拷贝是面试时经常被问到的问题,如果不能理解其本质原理,有可能会答非所问,给面试官留下不好的印象.另外,理解浅拷贝和深拷贝的原理,还可以帮助我们理解Python内存机制.这篇文章将会通过 ...

  10. Java拷贝——深拷贝与浅拷贝

    深拷贝和浅拷贝 值类型 vs 引用类型 在Java中,像数组.类Class.枚举Enum.Integer包装类等等,就是典型的引用类型,所以操作时一般来说采用的也是引用传递的方式: 但是Java的语言 ...

随机推荐

  1. 20220729 - DP训练 #2

    20220729 - DP训练 #2 时间记录 \(8:00-8:10\) 浏览题面 \(8:10-8:50\) T1 看题想到了建树,从每一个点遍历,若能遍历每一个点,则可以获胜 快速写完之后,发现 ...

  2. jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上

    jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上 1.JavaBean的使用 package com.zheng; public class BookBean { ...

  3. 齐博x1动态改变标签调用不同频道的数据

    标签默认需要设置标签参数 type 指定调用哪个频道的数据,比如下面的代码,需要默认指定商城的数据, {qb:tag name="qun_pcshow_shop001" type= ...

  4. $_SERVER['HTTP_USER_AGENT']:在PHP中HTTP_USER_AGENT是用来获取用户的相关信息的,包括用户使用的浏览器,操作系统等信息

    在PHP中HTTP_USER_AGENT是用来获取用户的相关信息的,包括用户使用的浏览器,操作系统等信息. 我机器:操作系统:WIN7旗舰版 64操作系统 以下为各个浏览器下$_SERVER['HTT ...

  5. SpringCloudAlibaba 微服务组件 Nacos 之配置中心源码深度解析

    大家好,这篇文章跟大家聊下 SpringCloudAlibaba 中的微服务组件 Nacos.Nacos 既能做注册中心,又能做配置中心,这篇文章主要来聊下做配置中心时 client 端的一些设计,主 ...

  6. srcddd

    目录 application assembler UserReq.go UserRsp.go dto MessageResult.go UserDTO.go services UserService. ...

  7. linux下进程的实际用户ID(有效组)和有效用户ID(有效组ID)

    实际用户ID(实际组ID):标识当前用户(所属组)是谁,当用户登陆时取自口令文件. 有效用户ID(有效组ID):用来决定我们(当前进程)对文件的访问权(即实际该进程的是以那个用户运行的). 一般情况下 ...

  8. kettel

    下载教程:(目前最高版本7.1) 1.网址:https://community.hitachivantara.com/docs/DOC-1009855 2.

  9. Forest + IDEA = 双倍快乐!ForestX 隆重登场

    Forest + IDEA = 双倍快乐!ForestX 隆重登场 Forest 是一款声明式的 Java 开源 HTTP 框架,相比它的前辈 Httpclient 和 OkHttp 更简明易懂.也更 ...

  10. 【RocketMQ】主从同步实现原理

    主从同步的实现逻辑主要在HAService中,在DefaultMessageStore的构造函数中,对HAService进行了实例化,并在start方法中,启动了HAService: public c ...