一、为什么要使用克隆?
想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。克隆分浅克隆和深克隆,浅克隆后的对象中非基本对象和原对象指向同一块内存,因此对这些非基本对象的修改会同时更改克隆前后的对象。深克隆可以实现完全的克隆,可以用反射的方式或序列化的方式实现。
二、如何实现对象克隆?
- 实现Cloneable接口并重写Object类中的clone()方法;
public class CloneDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Text s1=new Text("aaaa",18);
System.out.println("S1的姓名:"+s1.getName()+",年龄:"+s1.getAge());
//使用clone方法实现克隆
Object obj=s1.clone();
Text s2 = (Text)obj;
System.out.println("S2的姓名:"+s2.getName()+",年龄:"+s2.getAge());
//此处也可以实现复制,但是此种方法是将s1的地址给了s3,这是如果改变s3里面的东西s1也会跟着变化,但是由于s2是克隆的s1,所以s2并不会被改变
Student s3=s1;
System.out.println("S3的姓名:"+s3.getName()+",年龄:"+s3.getAge());
s3.setAge(20);
s3.setName("bbbb");
System.out.println("S1的姓名:"+s1.getName()+",年龄:"+s1.getAge());
System.out.println("S2的姓名:"+s2.getName()+",年龄:"+s2.getAge());
System.out.println("S3的姓名:"+s3.getName()+",年龄:"+s3.getAge());
}
}
//此处实现Cloneable接口
class Text implements Cloneable{
private String name;
private int age;
public Text() {
}
public Text(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
- 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆;
public class User implements Serializable{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//序列化测试
@Test
public void serializableTest() throws Exception {
//创建一个User对象,并将其赋值
User user = new User();
user.setName("aaaa");
user.setAge(25);
//创建内容存放位置,路径以及文件请提前创建好
File file = new File("H:\\test.txt");
FileOutputStream fos = new FileOutputStream(file);
//开始序列化
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(user);
oos.flush();
oos.close();
fos.close();
}
三、深拷贝和浅拷贝区别是什么?
- 浅拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。
- 深拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针和堆内存中的对象。
区别:
浅拷贝:当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是引用数据类型时,那么新对象和原对象的属性值其指向的是同一块内存地址。
深拷贝:会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
****编辑
****编辑
注:以上内容仅提供参考和交流,请勿用于商业用途,如有侵权联系本人删除!
注:此博客只是为了记忆相关知识点,大部分为网络上的文章,在此向各个文章的作者表示感谢!
标题:Java 常见的面试题(对象拷贝)
作者:wangjing
地址:https://www.codedblogs.cn/articles/2024/04/12/1712889323058.html