• java对象拷贝


    概念

    对象拷贝分为浅拷贝和深拷贝
    浅拷贝:只拷贝了源对象指向堆空间中内存地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化;
    深拷贝:源对象和新对象指向堆空间中内存地址不同,即使源对象的值发生变化时,拷贝对象的值也不会改变

    浅拷贝

    1)直接赋值

    Object a=new Object();
    Object b=a;
    
    • 1
    • 2

    这样只是将对象a的引用地址赋值给了b,当a对象值改变的时候,b对应的值也会改变
    2)使用Cloneable,重写clone方法实现浅拷贝
    首先创建两个类

    @Data
    @AllArgsConstructor
    public class Persion implements Cloneable{
    
        private String name;
    
        private Integer age;
    
        private Course course;
    
        @Override
        public Persion clone() throws CloneNotSupportedException {
            Persion persion = (Persion) super.clone();
            return persion;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    @Data
    @AllArgsConstructor
    public class Course {
    
        private String courseName;
    
        private Integer score;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试

        public static void main(String[] args) throws CloneNotSupportedException {
            Course course=new Course("语文",60);
            Persion red=new Persion("小红",10,course);
            Persion black=red.clone();
            black.setName("小明");
            black.getCourse().setCourseName("数学");
            System.out.println(black.getName()+"   "+black.getCourse().getCourseName()+"   "+black.hashCode()+"   "+black.getCourse().hashCode());
            System.out.println(red.getName()+"   "+red.getCourse().getCourseName()+"   "+red.hashCode()+"   "+red.getCourse().hashCode());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结果:

    小明   数学   -1611798689   48879495
    小红   数学   -1589896237   48879495
    
    • 1
    • 2

    结论:重写Cloneable的clone方法,只能拷贝当前对象,对于该对象引用的对象并没有改变;
    如果要当前对象的引用也拷贝则需要当前对象的引用对象也实现Cloneable的接口,重写clone方法;
    3)使用Spring提供的copyProperties方法实现浅拷贝

            Course course=new Course("语文",60);
            Persion red=new Persion("小红",10,course);
            Persion black=new Persion();
            BeanUtils.copyProperties(red,black);
            black.setName("小明");
            black.getCourse().setCourseName("数学");
            System.out.println(black.getName()+"   "+black.getCourse().getCourseName()+"   "+black.hashCode()+"   "+black.getCourse().hashCode());
            System.out.println(red.getName()+"   "+red.getCourse().getCourseName()+"   "+red.hashCode()+"   "+red.getCourse().hashCode());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果:

    小明   数学   -1611798689   48879495
    小红   数学   -1589896237   48879495
    
    • 1
    • 2

    深拷贝

    深拷贝对引用数据类型的成员变量中的所有的对象都开辟了内存空间,创建内存空间和拷贝整个对象,深拷贝相比于浅拷贝速度较慢并且花销较大。
    1)使用Cloneable,重写clone方法实现深拷贝
    即是将当前对象应用的所有对象都实现Cloneable并重写clone方法,但是这样比较麻烦;不常用

    序列化实现深拷贝

    2)使用apache的SerializationUtils实现深拷贝

    Persion black=SerializationUtils.clone(red);
    
    • 1

    结果:

    小明   数学   -1611798689   48879495
    小红   语文   -1571722113   67053619
    
    • 1
    • 2

    可以看到,Persion的hashCode和Course的hashCode都发生了变化,说明当前类中的引用类也是在内存中重新开辟空间存储;
    注意:SerializationUtils.clone()中的类要实现Serializable接口
    3)使用fastjson进行序列化

    Persion black= JSONObject.parseObject(JSONObject.toJSONString(red),Persion.class);
    
    • 1

    结果

    小明   数学   -1611798689   48879495
    小红   语文   -1571722113   67053619
    
    • 1
    • 2

    其它json也都是深拷贝

    使用序列化进行拷贝对象的注意事项

    静态成员变量、被transient修饰的成员变量 在序列化时是不会被序列化的。

  • 相关阅读:
    力扣:第81场双周赛
    邮件|gitpushgithub报错|Lombok注解
    sentinel熔断报java.lang.reflect.UndeclaredThrowableException
    使用VCPKG编译并使用Qt5
    spring 3.0新注解完全取代XML文件
    Linux系统下查看版本信息
    数据分析常用工具汇总
    prometheus 原理(架构,promql表达式,描点原理)
    Hive——DML(Data Manipulation Language)数据操作语句用法详解
    Oracle Primavera P6V7 SQL异常案例
  • 原文地址:https://blog.csdn.net/u010833154/article/details/126589494