前言
最近开始重构,Javabean也想全部替换成kotlin的data class,可data class使用有诸多限制,并没有Javabean使用的那么随心所欲。在此也记录下遇到的坑吧。
坑1:没有无参构造器
data class 没有无参构造器,创建此类至少要有一个参数。造成的不变就在于如果想手动创建数据,就要将所有的参数都赋值一遍。没有JavaBean直接通过无参构造器创建对象来的方便。
解决办法:虽然网上有很多的方式,包括使用什么插件,引入什么依赖,但有众多的限制,依然是不能随意的创建无参的data class实体类。如果使用data class的话,就不用想无参构造器创建了,可以使用替代的方式来减少繁琐。比如,data class 有 copy()
方法,可以直接copy出一个与原对象相同数据的对象,也可以传递某些参数来动态更改其数据。
val demo = DemoBean("hhh","男")
val copy = demo.copy()
val copy1 = demo.copy(name = "111")
val copy2 = demo.copy(sex = "女")
val copy3 = demo.copy(name = "222", sex = "嬲")
这样多少也减少了些工作量吧。
坑2 非空字段
在Javabean中,不存在什么非空字段,无非就是数据没有返回,调用的时候是空而已,只需要在代码中判断非空就行。而使用data class就要在书写的时候加非空判断。比如:
data class DemoBean(val name: String, val sex: String)
这样写,通过json转换来的字段必须包含 name
和 sex
,值可以为空,但必须得有这俩字段,否则转换不过来。
比如json为:
{"name":"11","sex","男"}
这样可以直接转换,但如果json是
{"name":"222"} 或者 {"sex","女"}
这样有缺省字段的情况下是无法转换成data class的。
解决办法1:所有字段都加非空判断?
将data class改成这样
data class DemoBean(val name: String?, val sex: String?)
允许字段为空,json缺省状态下依然可以使用,但带来的不便就是使用字段的时候都需要加判空标识符?
,其实也挺麻烦的。
解决办法2:约束api数据返回
代码层次上无法像javabean那么随心所欲的情况下,就直接从源头上解决问题吧。跟后台定好协议,文档上有的字段,必须全部返回,即便没有数据,也要返回空字段。这样带来的问题就是后续api接口数据字段只能增不能减,扩展性稍微差点。不过以我这么多年的工作经验来看,减字段优化接口还不如重新写一个接口更方便,减少线上出问题的风险。
坑3 复用性问题
从坑2里延伸来的问题,如果几个接口返回的数据很类似,有公共数据字段,各自还有各自独立的属性字段,在javabean中可以抽离出公共字段到基类,然后各自继承基类就可以实现复用。
但kotlin的data class也想类似javabean那种抽离出公共字段到一个data class,子类再继承使用就会出很大的问题。虽然data class可以继承,但是可继承的类有限,可以继承abstract
修饰的抽象类,可以继承sealed
修饰的密封类,像同为data class的数据类以及普通的不修饰的类,都无法继承。
解决办法1:不复用(废话),全字段写到对应的data class中。
解决办法2:放弃data class,写普通的kotlin类来封装数据,可以跟javabean一样,解决复用问题
解决办法3:使用abstract
修饰的抽象类来封装公共数据字段,各自data class继承此抽象类。
解决办法4:把所有的字段都放到同一个data class中,其中公共字段不需要添加非空判断,其余独立字段均加上非空判断,可以正常解析使用。
坑4 kotlin的反射依赖
项目中使用的fastJson,需要配合kotlin反射依赖才能顺利解析。
"org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
匹配好自己的kotlin版本即可。
添加混淆配置:
-keepattributes *Annotation*
-keep class kotlin.** { *; }
-keep class org.jetbrains.** { *; }
必加的依赖,否则一堆问题。
终极解决方案
出现上述问题的主要原因是用了fastjson,但如果换成Gson,上述的解析方面的问题就都不是问题了。无论字段是否缺省,无论是否配置kt的反射依赖,gson都可以完美的适配data class。少年,不想那么操蛋的配置,就换gson吧。
尾声
目前遇到这些坑,先记录下来,等以后还遇到什么问题,再补充吧。