java 深拷贝 和浅拷贝

163 阅读2分钟

1,前言:

在 Java 开发中,对象拷贝或者说对象克隆是常有的事,对象克隆最终都离不开直接赋值浅拷贝深拷贝 这三种方式,其中直接赋值应该是我们最常用的一种方式吧,对于浅拷贝和深拷贝可能用的少,所以或多或少存在一些误区,这篇文章会详细的介绍这三种对象克隆方式。

值类型:Java 的基本数据类型,例如 int、float 
引用类型:自定义类和 Java 包装类(string、integer

2,直接赋值:

直接赋值是我们最常用的方式,在我们代码中的体现是Persona = new Person();Person b = a,是一种简单明了的方式,但是它只是拷贝了对象引用地址而已,并没有在内存中生成新的对象,我们可以通过下面这个例子来证明这一点:

// person 对象
public class Person {
    // 姓名
    private String name;
    // 年龄
    private int age;
    // 邮件
    private String email;
    // 描述
    private String desc;
    ...省略get/set...
 }
 // main 方法
public class PersonApp {
   public static void main(String[] args) {
       // 初始化一个对象
       Person person = new Person("张三",20,"123456@qq.com","我是张三");
       // 复制对象
       Person person1 = person;
       // 改变 person1 的属性值
       person1.setName("我不是张三了");
        System.out.println("person对象:"+person);
        System.out.println("person1对象:"+person1);

   }
}

结果:

person对象:Person{name='我不是张三了', age=20, email='123456@qq.com', desc='我是张三'}
person1对象:Person{name='我不是张三了', age=20, email='123456@qq.com', desc='我是张三'}

可见:

直接赋值的方式没有生产新的对象,只是生新增了一个对象引用,直接赋值在 Java 内存中的模型大概是这样的

3, 浅拷贝 (不建议用啊)容易篡改掉数据

如果原型对象的成员变量是值类型,将复制一份给克隆对象,也就是说在堆中拥有独立的空间;

如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

换句话说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。 再白话一些 就是  

 A对象 . age =42      --------Aclone对象.age =42  这两个42 在内存堆里各占一块地

A对象 .媳妇对象 =123344er@(这个是媳妇内存的地址) -------Aclone对象 .媳妇对像=123344er@(同一个媳妇的地址) , 并没有开辟一块新空间创造一个新的媳妇,这个很危险啊,Aclone要是跟媳妇约会了, A对象肯定能发现啊 , 太可怕了 


4,深拷贝


5 序列化