Bootstrap

java克隆(clone)的两种实现方法

转载自:https://blog.csdn.net/leixiaotao_java/article/details/69525224

1.概念

a.Object的clone方法:

protected native Object clone() throws CloneNotSupportedException

b.clone方法重写原则:

  1. x.clone() != x为 true
  2. x.clone().getClass() == x.getClass()
  3. x.clone().equals(x)为 true
  4. 实现Cloneable接口(若不实现调用clone()时会抛出CloneNotSupportedException

c.Object的clone()方法为浅复制。

java克隆的2种方法

1.调用clone方法

  • 对象实现Cloneable接口并重写Object类中的clone()方法(调用Object的clone()实现,浅克隆方式);
(a)用户信息
public class Person implements Cloneable{
	private String name;
	private String sex;
	private Phone phone;
	/**
	 * 实现Cloneable接口,并重写clone方法
	 */
	@Override
	protected Object clone(){
		Person p=null;
		try {
/**
			 * 若要实现深克隆,此处就必须将对象中所有的复合数据类型统统单独复制拷贝一份,
			 * 但是实际开发中,无法确定对象中复合数据的种类和个数,
			 * 因此一般不采用此种方式实现深克隆
			 */
			p = (Person) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return p;
	}
	
	public Person(String name, String sex, Phone phone) {
		super();
		this.name = name;
		this.sex = sex;
		this.phone = phone;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Phone getPhone() {
		return phone;
	}
	public void setPhone(Phone phone) {
		this.phone = phone;
	}
	@Override
	public String toString() {
		return "[name=" + name + ", sex=" + sex + ", phone=" + phone
				+ "]";
	}
}
(b)手机信息
public class Phone{
 
	private String number;
	private String area;
	
	public Phone(String number, String area) {
		super();
		this.number = number;
		this.area = area;
	}
	
	public String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
	public String getArea() {
		return area;
	}
	public void setArea(String area) {
		this.area = area;
	}
	@Override
	public String toString() {
		return "[number=" + number + ", area=" + area + "]";
	}
}
(c)测试代码
public static void main(String[] args) {
		Person p=new Person("雷小涛", "man", new Phone("123456", "四川成都"));
		Person p2=(Person) p.clone();
		System.out.println("p:"+p.toString());
		System.out.println("p2:"+p2.toString());
		p2.setName("leixiaotao");
		p2.getPhone().setArea("四川乐山");
		System.out.println("-------其中一个对象修改值过后-------");
		System.out.println("p:"+p.toString());
		System.out.println("p2:"+p2.toString());
	}
  • 实现Cloneable接口,重写clone()方法,实现深克隆(调用Object的clone()实现,深克隆方式)

2.序列化深度拷贝
序列化一个对象,该类必须实Serializable标记性接口

(a)用户信息类
public class Person implements Serializable{
 
	private static final long serialVersionUID = -3936148364278781089L;
	
	private String name;
	private String sex;
	private Phone phone;
	
	public Person(String name, String sex, Phone phone) {
		super();
		this.name = name;
		this.sex = sex;
		this.phone = phone;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Phone getPhone() {
		return phone;
	}
	public void setPhone(Phone phone) {
		this.phone = phone;
	}
	@Override
	public String toString() {
		return "[name=" + name + ", sex=" + sex + ", phone=" + phone
				+ "]";
	}
}
(b)手机信息类
public class Phone implements Serializable{
 
	private static final long serialVersionUID = -4482468804013490322L;
	
	private String number;
	private String area;
	
	public Phone(String number, String area) {
		super();
		this.number = number;
		this.area = area;
	}
	
	public String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
	public String getArea() {
		return area;
	}
	public void setArea(String area) {
		this.area = area;
	}
	@Override
	public String toString() {
		return "[number=" + number + ", area=" + area + "]";
	}
}
(c)CloneUtil工具类
public class CloneUtil {
 
	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T clone(T object) throws Exception{
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(object);
 
        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        // 此处不需要释放资源,说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
        return (T) ois.readObject();
	}
}
(d)测试代码
public static void main(String[] args) throws Exception {
		Person p=new Person("雷小涛", "man", new Phone("123456", "四川成都"));
//		Person p2=(Person) p.clone();
		Person p2=CloneUtil.clone(p);
		System.out.println("p:"+p.toString());
		System.out.println("p2:"+p2.toString());
		p2.setName("leixiaotao");
		p2.getPhone().setArea("四川乐山");
		System.out.println("-------其中一个对象修改值过后-------");
		System.out.println("p:"+p.toString());
		System.out.println("p2:"+p2.toString());
	}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;