java 什么是clone浅拷贝和深拷贝

什么是浅拷贝
需要拷贝的源对象中的属性存在引用对象,拷贝后的对象中修改此引用对象的属性之后,源对象的引用值也跟着修改 
clone方法
clone()方法:对于基本类型是直接复制创建副本,对于引用类型,则是复制一个引用地址,不会复制引用所指对象
1.浅拷贝案例:

创建两个实体对象,Person,Address

		package com.yunsuibi.shallow.entity;
		
		public class Person implements Cloneable {
		
			private int age;
			private String name;
			private Address address;
		
			public Person(int age, String name, Address address) {
				this.age = age;
				this.name = name;
				this.address = address;
			}
		
			@Override
			public Object clone() throws CloneNotSupportedException {
				return super.clone();
			}
		
			public int getAge() {
				return age;
			}
		
			public void setAge(int age) {
				this.age = age;
			}
		
			public String getName() {
				return name;
			}
		
			public void setName(String name) {
				this.name = name;
			}
		
			public Address getAddress() {
				return address;
			}
		
			public void setAddress(Address address) {
				this.address = address;
			}
		
			public String display() {
				return "Person [age=" + age + ", name=" + name + ", address=" + address + "]";
			}
		}

		package com.yunsuibi.shallow.entity;
		
		public class Address {
		
			private String province;
			private String street;
		
			public Address(String province, String street) {
				this.province = province;
				this.street = street;
			}
		
			public String getProvince() {
				return province;
			}
		
			public void setProvince(String province) {
				this.province = province;
			}
		
			public String getStreet() {
				return street;
			}
		
			public void setStreet(String street) {
				this.street = street;
			}
		
			@Override
			public String toString() {
				return "Address [province=" + province + ", street=" + street + "]";
			}
		
		}

1.测试

	public static void main(String[] args) throws Exception {
			Person person = new Person(15, "张三", new Address("四川", "天府二街"));
	
			Person clonePerson = (Person) person.clone();
	
			System.out.println(person);
			System.out.println(clonePerson);
	
			System.out.println(person.display());
			System.out.println(clonePerson.display());
	
			clonePerson.setName("王麻子");
			clonePerson.setAge(20);
			Address address = clonePerson.getAddress();
			address.setStreet("天府四街");
			System.out.println(person.display());
			System.out.println(clonePerson.display());
		}

打印结果:

com.yunsuibi.shallow.entity.Person@7852e922
com.yunsuibi.shallow.entity.Person@4e25154f
Person [age=15, name=张三, address=Address [province=四川, street=天府二街]]
Person [age=15, name=张三, address=Address [province=四川, street=天府二街]]
Person [age=15, name=张三, address=Address [province=四川, street=天府四街]]
Person [age=20, name=王麻子, address=Address [province=四川, street=天府四街]]

注意:此时修改了address的复制对象后,源对象内容也跟着修改了,因此有了浅拷贝和深拷贝一说

2.下面案例讲解常用深拷贝方式:通过序列化实现拷贝

创建一个序列化对象



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

public class DeepClone implements Serializable{

	
	 /**
     * 利用序列化和反序列化进行对象的深拷贝
     * @return
     * @throws Exception
     */
    protected Object deepClone() throws Exception{
        //序列化
    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        //反序列化
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        return ois.readObject();
    }
	
}

Person对象修改为以下状态:

package com.yunsuibi.thorough2.entity;

public class Person extends DeepClone {

	private int age;
	private String name;
	private Address address;

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public String display() {
		return "Person [age=" + age + ", name=" + name + ", address=" + address + "]";
	}
}

Address对象修改为以下状态

package com.yunsuibi.thorough2.entity;

public class Address extends DeepClone {

	private String province;
	private String street;

	public Address(String province, String street) {
		this.province = province;
		this.street = street;
	}

	public String getProvince() {
		return province;
	}

	public void setProvince(String province) {
		this.province = province;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	@Override
	public String toString() {
		return "Address [province=" + province + ", street=" + street + "]";
	}

}

2.测试

public static void main(String[] args) throws CloneNotSupportedException {
		Person person = new Person(15, "张三", new Address("四川", "天府二街"));
        
        Person clonePerson = (Person) person.clone();
        
        System.out.println(person);
        System.out.println(clonePerson);
        
        System.out.println(person.display());
        System.out.println(clonePerson.display());
        
        clonePerson.setName("王麻子");
        clonePerson.setAge(20);
        Address address = clonePerson.getAddress();
        address.setStreet("天府四街");
        System.out.println(person.display());
        System.out.println(clonePerson.display());
	}

打印结果:

com.yunsuibi.thorough.entity.Person@7852e922
com.yunsuibi.thorough.entity.Person@4e25154f
Person [age=15, name=张三, address=Address [province=四川, street=天府二街]]
Person [age=15, name=张三, address=Address [province=四川, street=天府二街]]
Person [age=15, name=张三, address=Address [province=四川, street=天府二街]]
Person [age=20, name=王麻子, address=Address [province=四川, street=天府四街]]

此时修改了拷贝对象后,源对象没有跟着改变,深拷贝成功

还有一种方式,源对象需要实现Cloneable接口,重写clone方法,其中包含的所有引用对象也需要实现Cloneable接口,重写clone,
在源对象中clone中需要手动对引用对象进行clone并set源对象中,这种方式如果源对象中引用对象过多,代码就会冗余.不建议使用这种方式

个人博客 云随笔 为java而生

可以关注下博主的公众号,实时推送解决方案!
公众号

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值