深拷贝与浅拷贝

深拷贝和浅拷贝

 

深拷贝和浅拷贝是对对象的拷贝,一个对象中存在两种类型的属性,一种是基本数据类型,一种是实例对象的引用(引用数据类型)。

1:浅拷贝是指只会拷贝基本数据类型的值,以及实例对象的引用地址,并不会复制一份引用地址指向的对象,也就是浅拷贝出来的对象,内部的类属性指向的是同一个对象。

2:深拷贝是指既会拷贝基本类型的值,也会针对实例对象的引用地址指向的对象进行复制,深拷贝出来的对象,内部属性指向的不是同一个对象。

 

实现方式:

浅拷贝:

被复制类需要实现 Cloneable 接口,重写 clone 方法即可,对 person 类进行改造,使其可以支持浅拷贝。

public class Person implements Cloneable {
    private String name;   // 姓名
    private int age;             // 年龄
    private String email;    // 邮件
    private String desc;      // 描述
    private Person friend; // 朋友 
    /* 重写 clone 方法,需要将权限改成 public ,直接调用父类的 clone 方法就好了 */
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class PersonApp {
    public static void main(String[] args) throws Exception {
        // 初始化一个对象
        Person person = new Person("张三",20,"123456@qq.com","我是张三");
        // 复制对象
        Person person1 = (Person) person.clone();
        // 改变 person1 的属性值
        person1.setName("我是张三的克隆对象");
        // 修改 person age 的值
        person1.setAge(22);
        System.out.println("person对象:"+person);
        System.out.println();
        System.out.println("person1对象:"+person1);
    }
}
// person对象:Person{name='张三', age=20, email='123456@qq.com', desc='我是张三'}
// person1对象:Person{name='我是张三的克隆对象', age=22, email='123456@qq.com', desc='我是张三'}

原因:

String 和 Integer 等包装类都是不可变的对象。

当需要 修改 不可变对象的值时,需要在内存中生成一个新的对象来存放新的值,然后将原来的引用指向新的地址。

所以在这里我们修改了 person1 对象的 name 属性值,person1 对象的 name 字段指向了内存中新的 name 对象,但是我们并没有改变 person 对象的 name 字段的指向,所以 person 对象的 name 还是指向内存中原来的 name 地址,也就没有变化。

深拷贝:

相对于浅拷贝,深拷贝是一种完全拷贝,无论是值类型还是引用类型都会完完全全的拷贝一份,在内存中生成一个新的对象。拷贝对象和被拷贝对象没有任何关系,互不影响。

实现方式

实现Cloneable接口

class Address{
	String name;
	String eCode;
	public Address(	String na, String eC;)
	{
		this.name = na;
		this.eCode = eC;
	}
}

public class Person implements Cloneable {
    private String name;   // 姓名
    private int age;             // 年龄
    private String email;    // 邮件
	private Address address; // 
    private Person friend; // 朋友 
    /* 重写 clone 方法,需要将权限改成 public ,直接调用父类的 clone 方法就好了 */
    @Override
    public Object clone() throws CloneNotSupportedException {
    	Person newp = new Person();
    	newp.name = new String(this.name);
    	newp.age = this.age;
    	newp.email = new String(this.email);
		newp.address = new Address(this.address.name, this.address.eCode);
        return newp;
    }
}

实现Serializable接口

protected Son deepClone() throws IOException, ClassNotFoundException {
      Son son=null;
      //在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组中
      //默认创建一个大小为32的缓冲区
      ByteArrayOutputStream byOut=new ByteArrayOutputStream();
      //对象的序列化输出
      ObjectOutputStream outputStream=new ObjectOutputStream(byOut);//通过字节数组的方式进行传输
      outputStream.writeObject(this);  //将当前student对象写入字节数组中

      //在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区
      ByteArrayInputStream byIn=new ByteArrayInputStream(byOut.toByteArray()); //接收字节数组作为参数进行创建
      ObjectInputStream inputStream=new ObjectInputStream(byIn);
      son=(Son) inputStream.readObject(); //从字节数组中读取
      return son;
}

实现 Serializable 接口方式也可以实现深拷贝,而且这种方式还可以解决多层克隆的问题,多层克隆就是引用类型里面又有引用类型,层层嵌套下去。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗着,享受着

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值