Java深拷贝与浅拷贝

深拷贝与浅拷贝

在Java语言中(Python语言类似,可以导入copy包解决),我们对有时候对某一对象进行复制(克隆/拷贝)后发现,对其中某个对象的属性值进行了修改,与之相关的其它对象相应属性也随之变化。实际上,这是因为我们在进行对象克隆过程中,使用的是浅拷贝,也就是两个(或多个)对象引用指向同一个堆中对象实例。相反,深拷贝则是指拷贝的不同对象指向不同的堆中内存实例,因此深拷贝中对某一对象的修改不会影响其它的对象。

  • 示例:首先构造两个简单的类,其中Student类中属性字段有Person类的引用,结构如下:
    两个类的结构
  • Java代码展示浅拷贝和深拷贝(注释详细~)
public class CloneExample {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Person person = new Person(25, "小左");
	    Student student = new Student(person,80);
	    Student student2=null;
	    try {
			student2=student.clone();  //深拷贝,需要实现Cloneable重写clone函数
		} catch (CloneNotSupportedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	    System.out.println(student.hashCode());
	    System.out.println(student2.hashCode()); //打印两个对象的hashcode,深拷贝两对象hashcode不同
	    student.setGrade(70);
	    student2.getPerson().setName("小邵");
	    System.out.println(student.getGrade()+"\t"+student2.getGrade());
	    System.out.println(student.getPerson().getName()+"\t"+student2.getPerson().getName());
	    Student student3=student2;   //浅拷贝
	    System.out.println(student3.hashCode());  //两对象哈希值相同
	}
}

class Person implements Cloneable{   //实现Cloneable接口,重写clone()函数(调用父类clone方法)实现深拷贝
	private int age;  //姓名
	private String name;  //年龄
	public Person(int age,String name) {this.setAge(age);this.setName(name);}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person clone() throws CloneNotSupportedException {
		return (Person)super.clone();
	}
}

class Student implements Cloneable{  //实现Cloneable接口,重写clone()函数实现深拷贝
	private Person person;
	private int grade;  //分数
	public Student(Person person,int grade) {this.person=person;this.grade=grade;}
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public int getGrade() {
		return grade;
	}
	public void setGrade(int grade) {
		this.grade = grade;
	}
	public Student clone() throws CloneNotSupportedException{
		Student student=(Student)super.clone();
		//注意类属性为非基本类型引用时需要调用该引用的clone函数重新赋值,否则默认该属性的引用为浅拷贝
		student.setPerson(this.person.clone());  
		return student;
	}
}
  • 代码运行结果如下:
    运行结果
    可以看到student与student2为深拷贝,两者hashcode不同,以及两对象属性值的相互修改互不影响,而student2与student3则为浅拷贝(直接引用赋值方式),因为它们的hashcode相同。
  • 我们保持原有的代码不变,仅注释倒数第四行代码:
    代码注释
    运行结果如下:
    代码运行结果
    可以看到student和student2两个对象中的person却是指向同一堆中对象实例。这是因为我们在完全深拷贝时,没有调用person自身的clone()函数来给student2赋值,Java默认采用浅拷贝的方式将student的person浅拷贝给student2,导致我们在两个Student对象中修改person属性值,另一方都会受影响。因此,我们想要完全深拷贝某个对象,一定要在本层类重写clone()函数时调用上一层对象的clone()函数对该字段进行重新赋值(引用链有多长,我们重写clone()函数从底层开始,在本层类中调用上一层对象的clone()函数对该字段进行重新赋值)、

希望我的总结对你们有帮助,博客中相关问题欢迎询问探讨,相互学习。QQ:1476154032,以上。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中,深拷贝浅拷贝是指创建新对象并复制原有对象数据结构的过程,通常用于复杂的数据结构如数组、集合、对象等。它们的区别在于是否完全复制了对象的所有内容,包括嵌套的对象。 **浅拷贝**(Shallow Copy):它只是将原对象的引用复制给新对象。这意味着如果新对象中包含对原对象的引用,那么修改新对象会影响到原对象。在 Java 中,对于基本类型,浅拷贝就是简单地赋值;对于引用类型(如对象),则是复制指向内存地址的引用。 例如: ```java Object obj = new Object(); Object copy = obj; // 浅拷贝,copy 和 obj 引向同一块内存 List list = new ArrayList(); // 对象 List copyList = list; // 浅拷贝,list 和 copyList 都引用同一个ArrayList实例 ``` 修改 `copyList` 的元素会改变 `list`: ```java copyList.add("test"); System.out.println(list); // 输出 "test" ``` **深拷贝**(Deep Copy):则会对整个对象及其所有嵌套对象进行完整的副本操作,包括递归复制嵌套对象。这样改动一个深拷贝不会影响原始对象。在 Java 中,可以手动实现深拷贝,或者使用序列化反序列化的机制,比如 `Cloneable` 接口和 `Object.clone()` 方法(虽然不是所有类都实现了 Cloneable)。 例如: ```java Object obj = new Object(); Object deepCopy = SerializationUtils.deepCopy(obj); // 使用工具类的深拷贝方法 ``` 在这个例子中,`deepCopy` 是一个新的对象,它的状态与 `obj` 完全独立。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值