【面试问题】深拷贝和浅拷贝的区别?

简介: 【1月更文挑战第27天】【面试问题】深拷贝和浅拷贝的区别?

深拷贝和浅拷贝是关于复制对象时引用关系处理的两种不同策略。在理解深拷贝和浅拷贝的概念之前,首先需要了解对象引用和对象内部的数据存储。

对象引用和对象存储:

在 Java 中,对象变量存储的是对象的引用而不是对象本身。当一个对象被赋值给另一个对象变量时,实际上是复制了对象的引用,而不是对象的内容。这意味着两个对象变量可能引用同一个实际对象。、

classPerson {
Stringname;
Person(Stringname) {
this.name=name;
    }
}
publicclassReferenceExample {
publicstaticvoidmain(String[] args) {
Personperson1=newPerson("John");
Personperson2=person1; // person2 引用了 person1 引用的对象person2.name="Doe";
System.out.println(person1.name); // 输出 Doe    }
}

在上述例子中,person2person1 引用同一个 Person 对象,因此对 person2 的修改也会影响到 person1

浅拷贝(Shallow Copy):

浅拷贝是指只复制对象本身,而不复制对象内部的引用类型成员变量所引用的对象。简而言之,它只复制了对象的一层结构,而没有递归地复制对象内部的引用类型。

在 Java 中,可以通过实现 Cloneable 接口并覆盖 clone 方法来实现浅拷贝。

classAddress {
Stringcity;
Address(Stringcity) {
this.city=city;
    }
}
classPersonimplementsCloneable {
Stringname;
Addressaddress;
Person(Stringname, Addressaddress) {
this.name=name;
this.address=address;
    }
@OverrideprotectedObjectclone() throwsCloneNotSupportedException {
returnsuper.clone();
    }
}
publicclassShallowCopyExample {
publicstaticvoidmain(String[] args) throwsCloneNotSupportedException {
Addressaddress=newAddress("New York");
Personperson1=newPerson("John", address);
Personperson2= (Person) person1.clone();
person2.name="Doe";
person2.address.city="Los Angeles";
System.out.println(person1.name); // 输出 JohnSystem.out.println(person1.address.city); // 输出 Los Angeles    }
}

在上述例子中,person2 是通过 person1.clone() 得到的浅拷贝,当修改 person2 的属性时,person1 的属性也会受到影响。这是因为 address 是一个引用类型,浅拷贝只复制了引用,而没有复制引用指向的对象。

深拷贝(Deep Copy):

深拷贝是指在复制对象时,递归地复制对象内部的所有引用类型成员变量所引用的对象。深拷贝会创建一个新的对象,同时复制所有与之相关联的对象。

在 Java 中,实现深拷贝的方式可以是手动编写深拷贝方法,或者使用一些工具类,比如 Apache Commons Lang 库中的 SerializationUtils 或使用序列化和反序列化。

importorg.apache.commons.lang3.SerializationUtils;
classAddress {
Stringcity;
Address(Stringcity) {
this.city=city;
    }
}
classPersonimplementsjava.io.Serializable {
Stringname;
Addressaddress;
Person(Stringname, Addressaddress) {
this.name=name;
this.address=address;
    }
}
publicclassDeepCopyExample {
publicstaticvoidmain(String[] args) {
Addressaddress=newAddress("New York");
Personperson1=newPerson("John", address);
// 使用 SerializationUtils 进行深拷贝Personperson2=SerializationUtils.clone(person1);
person2.name="Doe";
person2.address.city="Los Angeles";
System.out.println(person1.name); // 输出 JohnSystem.out.println(person1.address.city); // 输出 New York    }
}

在上述例子中,SerializationUtils.clone 利用了 Java 对象序列化的特性,将对象序列化为字节流,然后再反序列化为一个新的对象,实现了深拷贝。

相关文章
|
3月前
|
Android开发 Kotlin
Android经典面试题之Kotlin的==和===有什么区别?
本文介绍了 Kotlin 中 `==` 和 `===` 操作符的区别:`==` 用于比较值是否相等,而 `===` 用于检查对象身份。对于基本类型,两者行为相似;对于对象引用,`==` 比较值相等性,`===` 检查引用是否指向同一实例。此外,还列举了其他常用比较操作符及其应用场景。
193 93
|
26天前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
2月前
|
编译器
经典面试题:变量的声明和定义有什么区别
在编程领域,变量的“声明”与“定义”是经典面试题之一。声明告诉编译器一个变量的存在,但不分配内存,通常包含变量类型和名称;而定义则为变量分配内存空间,一个变量必须至少被定义一次。简而言之,声明是告知变量形式,定义则是实际创建变量并准备使用。
|
2月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
140 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
2月前
|
前端开发 小程序 JavaScript
面试官:px、em、rem、vw、rpx 之间有什么区别?
面试官:px、em、rem、vw、rpx 之间有什么区别?
48 0
|
3月前
|
Java 关系型数据库 MySQL
面试官:GROUP BY和DISTINCT有什么区别?
面试官:GROUP BY和DISTINCT有什么区别?
95 0
面试官:GROUP BY和DISTINCT有什么区别?
|
4月前
|
算法 Java
【多线程面试题十八】、说一说Java中乐观锁和悲观锁的区别
这篇文章讨论了Java中的乐观锁和悲观锁的区别,其中悲观锁假设最坏情况并在访问数据时上锁,如通过`synchronized`或`Lock`接口实现;而乐观锁则在更新数据时检查是否被其他线程修改,适用于多读场景,并常通过CAS操作实现,如Java并发包`java.util.concurrent`中的类。
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
20天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
21天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
43 4