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

简介: 【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 对象序列化的特性,将对象序列化为字节流,然后再反序列化为一个新的对象,实现了深拷贝。

相关文章
|
12天前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
33 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
5天前
|
SQL Java Unix
Android经典面试题之Java中获取时间戳的方式有哪些?有什么区别?
在Java中获取时间戳有多种方式,包括`System.currentTimeMillis()`(毫秒级,适用于日志和计时)、`System.nanoTime()`(纳秒级,高精度计时)、`Instant.now().toEpochMilli()`(毫秒级,ISO-8601标准)和`Instant.now().getEpochSecond()`(秒级)。`Timestamp.valueOf(LocalDateTime.now()).getTime()`适用于数据库操作。选择方法取决于精度、用途和时间起点的需求。
17 3
|
16天前
|
存储 Java 程序员
Java面试题:请解释Java中的永久代(PermGen)和元空间(Metaspace)的区别
Java面试题:请解释Java中的永久代(PermGen)和元空间(Metaspace)的区别
43 11
|
12天前
|
Android开发
Android面试题之View的invalidate方法和postInvalidate方法有什么区别
本文探讨了Android自定义View中`invalidate()`和`postInvalidate()`的区别。`invalidate()`在UI线程中刷新View,而`postInvalidate()`用于非UI线程,通过消息机制切换到UI线程执行`invalidate()`。源码分析显示,`postInvalidate()`最终调用`ViewRootImpl`的`dispatchInvalidateDelayed`,通过Handler发送消息到UI线程执行刷新。
20 1
|
16天前
|
存储 安全 Java
Java面试题:在JVM中,堆和栈有什么区别?请详细解释说明,要深入到底层知识
Java面试题:在JVM中,堆和栈有什么区别?请详细解释说明,要深入到底层知识
30 3
|
2天前
|
消息中间件 调度 Android开发
Android经典面试题之View的post方法和Handler的post方法有什么区别?
本文对比了Android开发中`View.post`与`Handler.post`的使用。`View.post`将任务加入视图关联的消息队列,在视图布局后执行,适合视图操作。`Handler.post`更通用,可调度至特定Handler的线程,不仅限于视图任务。选择方法取决于具体需求和上下文。
11 0
|
9天前
|
Android开发 Kotlin
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
**Kotlin中的匿名函数与Lambda表达式概述:** 匿名函数(`fun`关键字,明确返回类型,支持非局部返回)适合复杂逻辑,而Lambda(简洁语法,类型推断)常用于内联操作和高阶函数参数。两者在语法、返回类型和使用场景上有所区别,但都提供无名函数的能力。
10 0
|
21天前
|
存储 算法 Java
Java面试之SpringCloud篇
Java面试之SpringCloud篇
35 1
|
21天前
|
缓存 NoSQL Redis
Java面试之redis篇
Java面试之redis篇
38 0
|
21天前
|
SQL 关系型数据库 MySQL
java面试之MySQL数据库篇
java面试之MySQL数据库篇
24 0
java面试之MySQL数据库篇