当前位置: 首页 > news >正文

Spring在不同类型之间也能相互拷贝?

场景还原

日常开发中,我们会定义非常多的实体,例如VO、DTO等,在涉及实体类的相互转换时,常使用Spring提供的BeanUtils.copyProperties,该类虽好,可不能贪用。

这不在使用过程中就遇到一个大坑,分析原来如此,我们定义伪代码如下:

    @Setter@Getterstatic class Father {private List<Son> childrenList;}@Setter@Getter@ToStringstatic class Mother {private List<Daughter> childrenList;}@Setter@Getterstatic class Son {private String name;private Integer age;}@Setter@Getterstatic class Daughter {private String name;private Integer age;}

我们定义了一家四口,老爸带儿子们,老妈带女儿们,我们运行如下伪代码:

public static void main(String[] args) {Father father = new Father();List<Son> childrenList = new ArrayList<Son>();Son son = new Son();son.setName("xiaoming");son.setAge(28);childrenList.add(son);father.setChildrenList(childrenList);Mother mother = new Mother();System.out.println("copy before:" + JSON.toJSONString(mother));BeanUtils.copyProperties(father, mother);System.out.println("copy after:" + JSON.toJSONString(mother));}

插播一则通告:本人在代码一线工作近八年时间,有非常丰富的面试经验,有需要优化简历,模拟面试的同学可以联系V:xiaolang1530368931。将简历优化成大厂面试官想看的,提前回答大厂面试官可能会问的问题,为进大厂做最后的冲刺。

大家猜下运行的结果是什么?老爸有没有成功甩手将儿子们扔给老妈?从定义上看,老爸和老妈的字段属性名称都是叫childrenList,但是泛型类型不一样,按照平常的用法,类型不一致,是没有办法进行拷贝的,但是我们运行后发现结果如下:

copy before:{}
copy after:{"childrenList":[{"age":28,"name":"xiaoming"}]}

奇怪,按道理前后应该都是空才对,这为什么成功拷贝了?

问题分析

不知道各位同学刚才有没有注意,我特别把泛型类型给飘红了,它确实是类型不一致,但更准确的说是泛型类型不一致。

这里就有一个非常重要的基础知识:

泛型只存在于编译阶段,运行时泛型信息会被擦除!

也就是我们的List<Son>和List<Daughter>全部都会被擦除为List<Object>,那两个List<Object>,属性名称一样不就能拷贝成功么!

而且非常奇特的是我们看下如下截图:

我们会发现Mother的原本定义的Daughter类型竟然变成Son类型了。从这个例子中切切时时感受到了泛型擦除。

看到这里,有些同学会问那这不是有bug吗,我的类型都被替换了。这点Java语言在设计泛型的时候就已经考虑了。虽然运行泛型被擦除了,但是当你使用的时候依然是你定义的具体类型,以上面这个例子,我们运行如下伪代码:

public static void main(String[] args) {Father father = new Father();List<Son> childrenList = new ArrayList<Son>();Son son = new Son();son.setName("xiaoming");son.setAge(28);childrenList.add(son);father.setChildrenList(childrenList);Mother mother = new Mother();System.out.println("copy before:" + JSON.toJSONString(mother));BeanUtils.copyProperties(father, mother);List<Daughter> daughterList = mother.getChildrenList();for (int i = 0; i < daughterList.size(); i++) {Daughter daughter = daughterList.get(i);System.out.println(daughter.getName());}System.out.println("copy after:" + JSON.toJSONString(mother));}

我们会发现copy after:并没有输出,输出结果如下:

copy before:{}
Exception in thread "main" java.lang.ClassCastException: com.github.TestClass$Son cannot be cast to com.github.TestClass$Daughterat com.github.TestClass.main(TestClass.java:32)

会发现虽然绕过了编译,但是使用的时候报类型转换异常。

总结

因为Java语言泛型的特性,目前Spring并没有提供重载方法来规避这个问题,但实际上这个问题也无需规避,本身运行起来类型一致就可以直接拷贝,只不过后续如果我们遇到此问题应该了解其根因。

分享一句非常喜欢的话:把根牢牢扎深,再等春风一来,便会春暖花开。

PS:以上引用信息以及图片均来自网络公开信息,如有侵权,请留言或联系

504401503@qq.com,立马删除。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Verilog学习日常】—牛客网刷题—Verilog企业真题—VL77
  • Linux 生成 git ssh 公钥
  • Linux 内核的版本控制
  • linux-系统备份与恢复-系统恢复
  • Redis主要问题
  • C语言习题~day25
  • mac 怎么查看CPU核数
  • Arthas jvm(查看当前JVM的信息)
  • 2024年全新deepfacelive如何对应使用直播伴侣-腾讯会议等第三方软件
  • 毕业设计选题:基于springboot+vue+uniapp的驾校报名小程序
  • 图像锐化的算法总结
  • Linux 基础入门操作 第九章 进程间通信之管道
  • 【数据结构初阶】链式二叉树接口实现超详解
  • S3C2440中断
  • AI学习指南深度学习篇-Adam的Python实践
  • 《Java编程思想》读书笔记-对象导论
  • 2019年如何成为全栈工程师?
  • Apache的基本使用
  • download使用浅析
  • JS+CSS实现数字滚动
  • js操作时间(持续更新)
  • Next.js之基础概念(二)
  • Objective-C 中关联引用的概念
  • 基于 Babel 的 npm 包最小化设置
  • 记录:CentOS7.2配置LNMP环境记录
  • 开源地图数据可视化库——mapnik
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 一个项目push到多个远程Git仓库
  • 怎么将电脑中的声音录制成WAV格式
  • 自制字幕遮挡器
  • # Apache SeaTunnel 究竟是什么?
  • #android不同版本废弃api,新api。
  • #nginx配置案例
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • $forceUpdate()函数
  • $nextTick的使用场景介绍
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (二)WCF的Binding模型
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (学习日记)2024.02.29:UCOSIII第二节
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • *p++,*(p++),*++p,(*p)++区别?
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .net Stream篇(六)
  • .net 后台导出excel ,word
  • .NET 设计一套高性能的弱事件机制
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .net8.0与halcon编程环境构建
  • .NET开源、简单、实用的数据库文档生成工具
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录