java的浅克隆和深克隆,你了解吗

克隆这个词最早出现在生物学,在java中引入这个概念是为了在特定的场景避免大量的get,set方法,java的克隆有两种方式: 深克隆和浅克隆,这里分析一下这两种克隆的方式实现方式和使用场景;

浅克隆

浅克隆的实现方式是实现Cloneable接口并重写Object类中的clone()方法;
现在随便写一个类

package com.lbh.test;

public class Person implements Cloneable{

	private String name; //姓名
	private int 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;
	}


	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}


	@Override
	public Object clone(){ 
		Person o = null; 
		try{ 
			o = (Person)super.clone(); 
		}catch(CloneNotSupportedException e){ 
			e.printStackTrace();
		}
		return o;
	}


	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	} 
	
}

测试克隆

package com.lbh.test;

public class TestOfClone {

	public static void main(String[] args) throws Exception {
		Person p1 = new Person("张山",20);
		Person p2 = (Person) p1.clone();  
		System.out.println(p1);
		System.out.println(p2);

	}

}

输出:

Person [name=张山, age=20]
Person [name=张山, age=20]

至此克隆完成,但是如果Person这个类的成员变量中有对象,这种方式就行不同了
新建一个Book类

package com.lbh.test;

public class Book {
	private String name;  //书名
	private String author; //作者
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public Book(String name, String author) {
		super();
		this.name = name;
		this.author = author;
	}
	@Override
	public String toString() {
		return "Book [name=" + name + ", author=" + author + "]";
	}

}

在person中加入一个Book类型的成员变量

	private String name; //姓名
	private int age; //年龄
	private Book book;

再次测试

	public static void main(String[] args) throws Exception {
		Person p1 = new Person("张山",20,new Book("风起陇西","马伯庸"));
		Person p2 = (Person) p1.clone();
		
		p2.getBook().setName("长安十二时辰"); 
		System.out.println(p1);
		System.out.println(p2);
		
	}

输出

Person [name=张山, age=20, book=Book [name=长安十二时辰, author=马伯庸]]
Person [name=张山, age=20, book=Book [name=长安十二时辰, author=马伯庸]]

这里可以看到,修改了p2中book的属性,p1中book的属性也会随之变化,造成这种结果的原因是浅克隆只复制了对象的引用地址,两个对象指向同一个内存地址
解决方案就是深克隆

深克隆

为了解决浅克隆中只是复制对象的引用地址,Java提供了深克隆
实现方式有多种,这里提供一种基于流的方式,
首先对应的Person类和Book实现Serializable接口

public class Person implements Cloneable,Serializable{

	private static final long serialVersionUID = 8832516388417668452L;

public class Book implements Serializable{
	private static final long serialVersionUID = 3405770039074127983L;

然后提供一个基于流的克隆方法

	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T clone(T obj) throws Exception{
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bout);
		oos.writeObject(obj);
		ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
		ObjectInputStream ois = new ObjectInputStream(bin);
		return (T) ois.readObject();
		
	}
	public static void main(String[] args) throws Exception {
		Person p1 = new Person("张山",20,new Book("风起陇右","马伯庸"));
		Person p2 = TestOfClone.clone(p1);
		p2.getBook().setName("长安十二时辰");
		System.out.println(p1);
		System.out.println(p2);  		

	}

再看输出结果

Person [name=张山, age=20, book=Book [name=风起陇右, author=马伯庸]]
Person [name=张山, age=20, book=Book [name=长安十二时辰, author=马伯庸]]

这个时候会发现,修改了p2中book的属性,p1中book的属性不会变化

应用场景

开发时遇到需要克隆对象只有基本属性,不包含对象属性时可以使用浅克隆;如果包含对象属性可以使用深拷贝;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值