java的克隆(深克隆和浅克隆)

概念

⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
换言之,浅复制仅仅复制所考虑的对象,而不
复制它所引用的对象。


⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用
其他对象的变量将指向被复制过的新对象,而不再是原
有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
浅克隆实现:覆写父类的clone
深克隆实现:
1.覆写父类的clone,并增加所有引用的clone
2.序列化

浅克隆

class Person implements Cloneable {
	String name;
	int age;


	public Person(String name, int age) {
		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 "名字:" + this.name + "年龄:" + this.age;
	}
}


public class SClass {


	public static void main(String[] args) {


		Person person = new Person("senssic", 20);
		System.out.println(person.toString());// Person的初始值
		Person p = (Person) person.clone();// 浅克隆Person
		p.name = "qiyu";// 修改克隆对象的值
		System.out.println(person.toString());// person对象克隆后的值,修改对象克隆后的值不会对原对象初始值产生影响


	}
}

运行结果:

名字:senssic年龄:20
名字:senssic年龄:20

这样虽然实现了克隆但是只能克隆本对象,如果有对象的引用就不能准确克隆了,这样只能属于浅克隆,比如:

package senssic.demo;


class Pro {
	String addre;
	int phon;


	public Pro(String addre, int phon) {
		this.addre = addre;
		this.phon = phon;
	}


	@Override
	public String toString() {
		return "地址:" + this.addre + "电话:" + this.phon;
	}


}


class Person implements Cloneable {
	String name;
	int age;
	Pro pro;


	public Person(String name, int age, Pro pro) {
		this.name = name;
		this.age = age;
		this.pro = pro;


	}


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


	@Override
	public String toString() {
		return "名字:" + this.name + "年龄:" + this.age + "--->"
				+ this.pro.toString();
	}
}


public class SClass {


	public static void main(String[] args) {


		Pro pro = new Pro("安徽", 123);
		Person person = new Person("senssic", 20, pro);
		System.out.println(person.toString());// Person的初始值
		Person p = (Person) person.clone();// 浅克隆Person
		p.name = "qiyu";// 修改克隆后对象的值
		System.out.println(person.toString());// 修改对象克隆后的值不会对原对象初始值产生影响
		p.pro.addre = "池州";// 修改克隆后对象引用的值
		System.out.println(person.toString());// 修改对象克隆后引用的值会对原对象初始值产生影响
	}
}
运行结果:

名字:senssic年龄:20--->地址:安徽电话:123
名字:senssic年龄:20--->地址:安徽电话:123
名字:senssic年龄:20--->地址:池州电话:123

深克隆

1.覆写父类的clone,并增加所有引用的clone

package senssic.demo;


class Pro implements Cloneable {
	String addre;
	int phon;


	public Pro(String addre, int phon) {
		this.addre = addre;
		this.phon = phon;
	}


	@Override
	public String toString() {
		return "地址:" + this.addre + "电话:" + this.phon;
	}


	@Override
	public Object clone() {
		Object object = null;
		try {
			object = super.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return object;
	}
}


class Person implements Cloneable {
	String name;
	int age;
	Pro pro;


	public Person(String name, int age, Pro pro) {
		this.name = name;
		this.age = age;
		this.pro = pro;


	}


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


		return o;
	}


	@Override
	public String toString() {
		return "名字:" + this.name + "年龄:" + this.age + "--->"
				+ this.pro.toString();
	}
}


public class SClass {


	public static void main(String[] args) {


		Pro pro = new Pro("安徽", 123);
		Person person = new Person("senssic", 20, pro);
		System.out.println(person.toString());// Person的初始值
		Person p = (Person) person.clone();// 浅克隆Person
		p.name = "qiyu";// 修改克隆后对象的值
		System.out.println(person.toString());// 修改对象克隆后的值不会对原对象初始值产生影响
		p.pro.addre = "池州";// 修改克隆后对象引用的值
		System.out.println(person.toString());// 修改对象克隆后引用的值也不会对原对象初始值产生影响
	}
}
运行结果:
名字:senssic年龄:20--->地址:安徽电话:123
名字:senssic年龄:20--->地址:安徽电话:123
名字:senssic年龄:20--->地址:安徽电话:123

2.利用序列化进行深克隆

必须实现序列化接口
package senssic.demo;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;

class Pro implements Serializable {// 需要实现序列化接口
	String addre;
	int phon;

	public Pro(String addre, int phon) {
		this.addre = addre;
		this.phon = phon;
	}

	@Override
	public String toString() {
		return "地址:" + this.addre + "电话:" + this.phon;
	}

}

class Person implements Serializable {
	String name;
	int age;
	Pro pro;

	public Person(String name, int age, Pro pro) {
		this.name = name;
		this.age = age;
		this.pro = pro;

	}

	public Object deepClone() {// 将对象写到流里
		Object object = null;
		try {
			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			ObjectOutputStream oo = new ObjectOutputStream(bo);
			oo.writeObject(this);// 从流里读出来
			ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
			object = new ObjectInputStream(bi).readObject();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (OptionalDataException e) {
			e.printStackTrace();

		} catch (IOException e) {
			e.printStackTrace();
		}

		return object;
	}

	@Override
	public String toString() {
		return "名字:" + this.name + "年龄:" + this.age + "--->"
				+ this.pro.toString();
	}
}

public class SClass {

	public static void main(String[] args) {

		Pro pro = new Pro("安徽", 123);
		Person person = new Person("senssic", 20, pro);
		System.out.println(person.toString());// Person的初始值
		Person p = (Person) person.deepClone();// 浅克隆Person
		p.name = "qiyu";// 修改克隆后对象的值
		System.out.println(person.toString());// 修改对象克隆后的值不会对原对象初始值产生影响
		p.pro.addre = "池州";// 修改克隆后对象引用的值
		System.out.println(person.toString());// 修改对象克隆后引用的值也不会对原对象初始值产生影响
	}
}
运行结果:
名字:senssic年龄:20--->地址:安徽电话:123
名字:senssic年龄:20--->地址:安徽电话:123
名字:senssic年龄:20--->地址:安徽电话:123



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值