java基础:浅拷贝与深拷贝(实际开发中遇到的深拷贝问题)
创始人
2025-05-29 10:20:42
0

1、java中深浅拷贝的区别?

  • 浅拷贝:只对基本数据类型进行拷贝,对于引用数据类型只是进行了引用的传递,没有真实的创建一个新的对象,则是浅拷贝;(参数引用传递中的改变源对象情况)
    在这里插入图片描述

  • 深拷贝:在对引用数据类型拷贝过程中,创建了一个新的对象,并且复制了对象内的所有成员变量,则是深拷贝(参数引用传递中的不改变源对象情况)

在这里插入图片描述

1.1 java浅拷贝的实现?

Cloneable 接口,并覆写 clone() 方法,clone()方法实现的是对当前对象进行拷贝。

1.2 java深拷贝的实现

  • Cloneable 接口,并覆写 clone() 方法
    需要拿到拷贝自己后产生的新的对象,然后对新的对象的引用类型再调用拷贝操作,实现对引用类型成员变量的深拷贝。
    实现两次clone,第一次得到当前对象浅拷贝,然后再对新的对象引用类型调用拷贝实现深拷贝
  • 序列化对象,再反序列化回来,然后就可以得到一个新的对象,

1.3 什么是序列化?(serialization涉及到IO部分)

将对象写入到io流中,反序列化是从io流中恢复对象;

2、java方法中的参数传递?(都是传递副本,值传递,java中没有引用传递)

问:当一个对象当作参数传递到一个方法之后,此方法可以改变对象属性,并且可以返回变化后的对象,那么这里是值传递还是对象传递。。
答:java中只有值传递参数

  • 如果参数类型是基本数据类型,值传递,改变副本的值不会改变原始数据的值;
  • 如果参数类型是引用数据类型,传过来的是对象地址副本,如果方法中没有改变地址的值,方法内针对对象的改变会影响到传入的参数;(浅拷贝)
  • 如果参数类型是引用数据类型,函数中改变了副本的地址,比如new一个,也就是副本指向一个新的地址,此时方法中针对对象的改变不会影响到传入参数对象;(深拷贝)

3. 开发中遇到的数据拷贝问题

刚工作的时候,业务代码开发过程中遇到过这种直接修改了引用数据类型参数导致的数据异常问题。

有问题的代码如下:

  public SettingsExtVo filterRateByCity(SettingsExtVo settingsExtVo,String cityCode){if (cityCode == null){return settingsExtVo;}List groups = settingsExtVo.getGroups();//    SettingsExtVo settingsExtVoNew = new SettingsExtVo();// 定义一个新的ListList groupExtVOList = com.google.api.client.util.Lists.newArrayList();// 遍历groups筛选出满足城市条件的groupgroups.forEach(groupExtVO -> {if (groupExtVO.getCondition() != null){Map condition = groupExtVO.getCondition();if (condition.get("cityGuid") != null){List cityList = Arrays.asList(condition.get("cityGuid").split(","));if (cityList.contains(cityCode)){groupExtVOList.add(groupExtVO);}}}});if (CollectionUtils.isEmpty(groupExtVOList)){groups.forEach(groupExtVO1 -> {if (groupExtVO1.getCondition() == null){groupExtVOList.add(groupExtVO1);}});}// 修改引用传参数,值传递传的是对象地址值,此时对地址对应的对象进行了修改。settingsExtVo.setGroups(groupExtVOList);return settingsExtVo;}

上述代码功能主要是对一个对象中的list列表数据进行筛选,并且返回筛选后的数据。

代码中对SettingsExtVo的实例对象进行了修改,而该对象是本地缓存的数据对象,通过该方法对本地缓存的对象进行修改,这就导致后续程序使用该缓存对象的时候出现数据丢失的问题。

修复后的代码逻辑(使用json序列化,深拷贝出一个全新的对象)

  /*** 根据头盔城市筛选出对应的评价问题** @param settingsExtVo* @param cityCode* @return SettingsExtVo*/public SettingsExtVo filterRateByCity(SettingsExtVo settingsExtVo,String cityCode){// 利用Json序列化实现对象深拷贝String jsonString = JsonUtils.json2String(settingsExtVo);SettingsExtVo settingsExtVoNew = JsonUtils.json2Object(jsonString,SettingsExtVo.class);List groups = settingsExtVo.getGroups();// 定义一个新的ListList groupExtVOList = Lists.newArrayList();// 遍历groups筛选出满足城市条件的groupgroups.forEach(groupExtVO -> {if (groupExtVO.getCondition() != null && cityCode != null){Map condition = groupExtVO.getCondition();if (condition.get("cityGuid") != null){List cityList = Arrays.asList(condition.get("cityGuid").split(","));if (cityList.contains(cityCode)){groupExtVOList.add(groupExtVO);}}}});if (CollectionUtils.isEmpty(groupExtVOList)){groups.forEach(groupExtVO1 -> {if (groupExtVO1.getCondition() == null){groupExtVOList.add(groupExtVO1);}});}settingsExtVoNew.setGroups(groupExtVOList);return settingsExtVoNew;}

第二种修复方案是不修改引用参数对象,利用参数对象做筛选,但是新建一个对象来存储筛选的数据,并且也返回这个新创建的对象;

  /*** 按照group的匹配规则来筛选评价问题* @param settingsExtVo* @param cityCode* @return*/public List filterRateByCondition(SettingsExtVo settingsExtVo,String cityCode,String npsType){List groups = settingsExtVo.getGroups();// 定义一个新的ListList groupExtVOList = Lists.newArrayList();//遍历groups筛选出满足头盔城市条件的groupgroups.forEach(groupExtVO -> {if (groupExtVO.getCondition() != null && cityCode != null){Map condition = groupExtVO.getCondition();if (condition.get("cityGuid") != null){List cityList = Arrays.asList(condition.get("cityGuid").split(","));if (cityList.contains(cityCode) && groupExtVO.getDisplay().equals(true)){groupExtVOList.add(groupExtVO);}}}});// 按头盔城市筛选为空,则再次按照nps模式进行筛选if (CollectionUtils.isEmpty(groupExtVOList)){groups.forEach(groupExtVO -> {if (groupExtVO.getCondition() != null && Objects.nonNull(npsType)){if (groupExtVO.getCondition().get("npsType").equals(npsType)){groupExtVOList.add(groupExtVO);}}});}//  如果按照已有规则筛选都为空,则筛选无规则groupif (CollectionUtils.isEmpty(groupExtVOList)){groups.forEach(groupExtVO1 -> {if (Objects.isNull(groupExtVO1.getCondition())){groupExtVOList.add(groupExtVO1);}});}return groupExtVOList;}

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...