网站首页 > java教程 正文
我们知道,在计算机内存中,每个对象都有一个地址,这个地址指向对象在内存中存储的位置。当我们使用变量引用一个对象时,实际上是将该对象的地址赋值给变量。因此,如果我们将一个对象复制到另一个变量中,实际上是将对象的地址复制到了这个变量中。这就涉及到我们今天要说的深拷贝和浅拷贝。
一、深拷贝和浅拷贝的区别
1、浅拷贝是指将一个对象复制到另一个变量中,但是只复制对象的地址,而不是对象本身。也就是说,原始对象和复制对象实际上是共享同一个内存地址的。
2、深拷贝是指将一个对象及其所有子对象都复制到另一个变量中,也就是说,它会创建一个全新的对象,并将原始对象中的所有属性或元素都复制到新的对象中。因此,如果我们修改复制对象中的属性或元素,原始对象中对应的属性或元素不会受到影响。
二、深拷贝和浅拷贝的实现
1、浅拷贝
实现对象拷贝的类,需要实现 Cloneable 接口,并覆写 clone() 方法。在Java中,我们常用的各种BeanUtils基本也都是浅拷贝的。
package com.demo;
public class CopyDemo {
public static void main(String[] args) {
Person person1 = new Person(new Car("鄂A123345"));
Person person1Copy = person1.clone();
System.out.println(person1.getCar() == person1Copy.getCar());
}
}
class Car implements Cloneable{
private final String carNo;
public String getCarNo() {
return carNo;
}
public Car(String carNo) {
this.carNo = carNo;
}
@Override
public Car clone() {
try {
return (Car) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
class Person implements Cloneable {
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public Person(Car car) {
this.car = car;
}
@Override
public Person clone() {
try {
Person person = (Person) super.clone();
return person;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
从输出结构就可以看出, person1 的克隆对象和 person1 使用的仍然是同一个 Car 对象。
2、深拷贝
实现Cloneable接口,重写clone()。在Object类中定义了一个clone方法,这个方法其实在不重写的情况下,其实也是浅拷贝的。如果想要实现深拷贝,就需要重写clone方法,而想要重写clone方法,就必须实现Cloneable,否则会报CloneNotSupportedException异常。
这里我们简单对 Person 类的 clone() 方法进行修改,连带着要把 Person 对象内部的 Car 对象一起复制。
@Override
public Person clone() {
try {
Person person = (Person) super.clone();
person.setCar(person.getCar().clone());
return person;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
之后,再次在执行一下上面的main测试代码,就可以发现,这时候person1 的克隆对象和 person1 包含的 Car 对象已经是不同的了。
这种方式就能实现深拷贝,但是问题是如果我们在Person中有很多个对象,那么clone方法就写的很长,而且如果后面有修改,在Person中新增属性,这个地方也要改。
这时候可以借助序列化来实现深拷贝。先把对象序列化成流,再从流中反序列化成对象,这样就一定是新的对象了。
在实际开发过程中可以使用Apache Commons Lang中提供的SerializationUtils工具实现。我们先修改下上面的Person和Car类,使他们实现Serializable接口,否则是无法进行序列化的。
class Car implements Serializable
class Person implements Serializable
然后在需要拷贝的时候:
Person person1CopyNew= (Person)SerializationUtils.clone(person1);
以上详细讲解了java对象的深拷贝和浅拷贝的区别和应用,大家不妨动手试一试,了解一下java的高级用法,有问题可以在评论区一起交流!
猜你喜欢
- 2024-10-19 Python 中赋值、浅拷贝、深拷贝的区别是什么?
- 2024-10-19 Java 对象拷贝原理剖析(java 对象拷贝原理剖析)
- 2024-10-19 认识Object类和深浅拷贝!(阐述object.assign的用法,深拷贝与浅拷贝的区别?)
- 2024-10-19 三面“有赞”Java岗斩获offer:Spring+JVM+并发锁+分布式+算法
- 2024-10-19 谈谈 Java 开发中的对象拷贝(java对象拷贝工具类)
- 2024-10-19 深入浅出Java中的clone克隆方法,写得也太棒了
- 2024-10-19 深拷贝和浅拷贝之list、dataframe
- 2024-10-19 对象拷贝java 浅谈(java对象的拷贝)
- 2024-10-19 Java克隆对象需要知道的事(java克隆的作用)
- 2024-10-19 Java的Object十二个常用方法,你用过几个?
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)