java对象的浅拷贝和深拷贝

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class Student implements Cloneable, Serializable {

int id;

Map<String, String> score = new HashMap<String, String>();

public Student(int id, Map<String, String> score) {
super();
this.id = id;
this.score = score;
}

/**
* 浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属
* 性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,
* 因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
*/
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO 自动生成的方法存根
return super.clone();
}

/**
*
* 深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生
* 深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
*/
protected Object deepClone() throws CloneNotSupportedException,
IOException, ClassNotFoundException {

// 将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
// 从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return oi.readObject();

}

}


import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


public class T {

/**
* @param args
* @throws CloneNotSupportedException
* @throws ClassNotFoundException
* @throws IOException
*/
public static void main(String[] args){
// TODO 自动生成的方法存根

try {
Map<String,String> score =new HashMap<String,String>();
score.put("English", "139");
score.put("Math", "146");

Student s1=new Student(1,score);
Student s2=(Student) s1.clone();//浅拷贝
Student s3=(Student) s1.deepClone();//深拷贝

s1.score.put("Chinese", "147");

System.out.println(s2.score.get("Math")+" "+s2.score.get("Chinese"));//139 147
System.out.println(s3.score.get("Math")+" "+s3.score.get("Chinese"));//139 null

} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
### Java浅拷贝深拷贝的区别及实现方式 #### 1. **基本概念** 在Java编程中,对象的拷贝分为两种主要形式:浅拷贝深拷贝。这两种拷贝方式的核心差异在于它们对待对象内部引用字段的不同处理策略[^1]。 - 浅拷贝是指创建一个新的对象,并将原对象中的所有字段按位复制到新对象中。如果字段是基础数据类型,则直接复制其值;如果是引用类型,则只复制引用地址而不克隆实际的对象实例[^5]。 - 深拷贝不仅会复制对象本身,还会递归地复制该对象所包含的所有子对象,从而确保源对象及其所有嵌套对象与目标对象完全独立[^3]。 --- #### 2. **实现方式** ##### (1)**浅拷贝** 在Java中,默认情况下通过继承`Object`类并覆盖其受保护的方法`clone()`即可实现浅拷贝。具体步骤如下: - 被复制的类需实现`Cloneable`接口以表明支持克隆操作; - 重写`clone()`方法,在其中调用`super.clone()`完成初步的字段复制过程[^2]。 下面给出一个简单的示例代码片段用于演示如何执行浅拷贝: ```java class Person implements Cloneable { private String name; private Address address; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } // Getter and Setter methods omitted for brevity. } ``` 在这个例子当中,当我们尝试克隆一个Person实例时,虽然name属性会被正常复制成新的String对象,但由于address是一个复合型成员变量(即另一个类Address的实例),所以实际上只是简单地把原有的reference赋给了新产生的person object而已[^4]。 --- ##### (2)**深拷贝** 为了达到真正的深拷贝效果,除了遵循上面提到的步骤外,还需要额外采取措施去分别处理那些非基本类型的成员变量。通常有两种通用做法可供选择: - **手动逐个克隆**: 在自定义的`clone()`方法里面针对每一个非基本类型的field单独调用相应的克隆逻辑。 ```java @Override protected Object clone() throws CloneNotSupportedException { Person clonedPerson = (Person) super.clone(); clonedPerson.address = (Address) this.address.clone(); // Assuming Address also overrides clone(). return clonedPerson; } ``` 这里假设Address也已经适当地覆写了自身的`clone()`函数[^3]。 - **序列化反序列化技术**: 利用Java内置的对象流机制自动完成深层次的数据分离工作。这种方法无需显式修改原有业务模型就能轻松获得完整的副本,但前提是参与序列化的各个组件都必须标记为Serializable才行。 ```java public static <T extends Serializable> T deepCopy(T obj) throws Exception { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject(obj); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bis); return (T)in.readObject(); } ``` 上述辅助工具接受任意可串行化的输入参数obj并通过中间媒介暂存后再还原出来形成最终的结果[^3]。 --- ### 总结表格对比 | 特性 | 浅拷贝 | 深拷贝 | |--------------------|---------------------------------------------|----------------------------------------------| | 定义 | 创建新对象并将原始对象的部分内容复制过去 | 将整个对象树全部重新构建一遍 | | 引用关系 | 子对象仍共享同一份实体 | 各级节点均拥有各自独立的存在 | | 实现难度 | 较易 | 更加复杂 | | 效率 | 高 | 相对较低 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值