美文网首页
java浅克隆与深克隆

java浅克隆与深克隆

作者: 喏喏2021 | 来源:发表于2024-08-20 17:18 被阅读0次

    一. 基本概念

    • 浅克隆
      只复制对象的基本数据类型(byte,short,int,long,float,double,boolean,char),不复制引用类型
    • 深克隆
      复制对象的基本类型和引用类型

    二. 示例

    • 以下为2个用于测试的类
    /**
     * 地址类
     */
    @Data
    class Address {
        private String name;
    }
    
    /**
     * 小猫类
     */
    @Data
    class Cat implements Cloneable<Cat> {
        //名字
        private String name;
        //体重,单位千克
        private BigDecimal weight;
        //地址
        private Address address;
    
        @Override
        public Cat clone() {
            try {
                return (Cat)super.clone();
            } catch (CloneNotSupportedException e) {
                throw new CloneRuntimeException(e);
            }
        }
    }
    
    • 浅复制操作
    Cat cat1 = new Cat();
            cat1.setName("金金");
            cat1.setWeight(new BigDecimal("10.8"));
            Address address = new Address();
            address.setName("宠物店");
            cat1.setAddress(address);
    
            Cat cat2 = cat1.clone();
            //此时可以看一下两只猫属性是否一致,此时呢,两只猫属性都是一样的
            log.info("浅复制后 cat1:{}", cat1);
            log.info("浅复制后 cat2:{}", cat2);
    
            //最近伙食比较好,又长了一斤
            cat1.setWeight(cat1.getWeight().add(BigDecimal.ONE));
            //第2只猫想,我得有个自己的名字呀
            cat2.setName("小猫");
            cat2.getAddress().setName("主人家里");
            //此时呢,已经有了一些变化,两只猫的名字和体重已经有了差异,但地址因为是引用类型,现在成了一样的
            log.info("浅复制 修改后 cat1:{}", cat1);
            log.info("浅复制 修改后 cat2:{}", cat2);
    
    • 浅复制后打印的结果
      16:30:53.540 [main] INFO hutool.CloneTest - 浅复制后 cat1:Cat(name=金金, weight=10.8, address=Address(name=宠物店))
      16:30:53.543 [main] INFO hutool.CloneTest - 浅复制后 cat2:Cat(name=金金, weight=10.8, address=Address(name=宠物店))
      16:30:53.543 [main] INFO hutool.CloneTest - 浅复制 修改后 cat1:Cat(name=金金, weight=11.8, address=Address(name=主人家里))
      16:30:53.543 [main] INFO hutool.CloneTest - 浅复制 修改后 cat2:Cat(name=小猫, weight=10.8, address=Address(name=主人家里))
    • 分析:
      cat2完成了成功的复制,和cat1结果一样,当修改了各自的信息后,基本类型是会各自保存,
      而引用类型因为是同一个对象,所以两个对象都保持一致
    • 深复制操作
            cat2 = DeepCopyUtil.deepCopy(cat1,Cat.class);
            log.info("深复制后 cat1:{}", cat1);
            log.info("深复制后 cat2:{}", cat2);
            cat2.getAddress().setName("还在主人家里");
            log.info("深复制后 修改cat2 cat1:{}", cat1);
            log.info("深复制后 修改cat2 cat2:{}", cat2);
    
    • 深复制后打印的结果
      16:30:53.844 [main] INFO hutool.CloneTest - 深复制后 cat1:Cat(name=金金, weight=11.8, address=Address(name=主人家里))
      16:30:53.844 [main] INFO hutool.CloneTest - 深复制后 cat2:Cat(name=金金, weight=11.8, address=Address(name=主人家里))
      16:30:53.844 [main] INFO hutool.CloneTest - 深复制后 修改cat2 cat1:Cat(name=金金, weight=11.8, address=Address(name=主人家里))
      16:30:53.844 [main] INFO hutool.CloneTest - 深复制后 修改cat2 cat2:Cat(name=金金, weight=11.8, address=Address(name=还在主人家里))
    • 分析
      深复制后,修改了cat2的地址信息,这时cat1的地址不会发生变化
    • 备注,深复制工具方法
    public class DeepCopyUtil {
        private static final ObjectMapper objectMapper = new ObjectMapper();
    
        public static <T> T deepCopy(T original, Class<T> clazz){
            if(original==null){
                return null;
            }
    
            try {
                //将对象序列化为JSON字符串
                String json = objectMapper.writeValueAsString(original);
                //将JSON字符串反序列化为新对象
                return objectMapper.readValue(json, clazz);
            }catch(Exception e){
                throw new RuntimeException("无法进行深拷贝", e);
            }
        }
    }
    

    使用json进行序列化和反序列化,也可以将对象序列化为字符流,再反序列化回来,
    在需要高效性能的环境,可以使用第三方库Kryo。

    相关文章

      网友评论

          本文标题:java浅克隆与深克隆

          本文链接:https://www.haomeiwen.com/subject/jruvkjtx.html