kotlin data class相比于JavaBean有诸多的限制,并没有JavaBean使用的那么随心所欲。在此记录下使用data class遇到的问题。
1.没有无参构造器
通过查看字节码我们会发现,data class被编译成了一个final class,而且没有默认的无参构造器。所以创建此类至少要有一个参数,造成的不变就在于如果你想手动创建数据,就得要将所有的参数都赋值一遍,没有JavaBean直接通过无参构造器创建对象来的方便。
解决办法1:在data class 里面所有字段都写上默认值,就可以不传入参数创建类,或者通过具名参数的方式,传入某几个参数创建类。
data class Person(
var age: Int? = 0,
var name: String? = "",
val sex: Boolean? = false
)
val teacher = Person()
val student = Person(name = "lyx")
解决办法2:虽然网上有很多的方式,包括使用什么插件,引入什么依赖,但有众多的限制,依然是不能随意的创建无参的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 Person(
var age: Int,
var name: String,
val sex: Boolean
)
这样写,通过json转换来的字段必须包含 age、name
和 sex
,值可以为空,但必须得有这三个字段,否则转换不过来。
比如json为:
{"name":"lyx","age":18,"sex",true}
这样可以直接转换。但如果json是
{"name":"lyx"} 或者 {"age":18,"sex",true}
这样有缺省字段的情况下是无法转换成data class的。
解决办法1:所有字段都加非空判断?
将data class改成这样
data class Person(
var age: Int?,
var name: String?,
val sex: Boolean?
)
允许字段为空,json缺省状态下依然可以使用,但带来的不便就是使用字段的时候都需要加判空标识符?
,其实也挺麻烦的。
解决办法2:约束api数据返回
代码层次上无法像JavaBean那么随心所欲的情况下,就直接从源头上解决问题吧。跟后台定好协议,文档上有的字段,必须全部返回,即便没有数据,也要返回空字段。这样带来的问题就是后续api接口数据字段只能增不能减,扩展性稍微差点。不过以我这么多年的工作经验来看,减字段优化接口还不如重新写一个接口更方便,减少线上出问题的风险。
解决方案3:
出现上述问题的主要原因是用了fastjson,但如果换成Gson,上述的解析方面的问题就不是问题了。gson可以完美的适配data class。
3.继承和复用性问题
data class可以继承,但是不能被继承。问题1的时候我们说过,data class被编译成了final class,是不能被继承的。
但是有种很常见的业务场景:比如接口request类有很多公用的参数,但是不同的接口又有其独立的参数。在JavaBean中可以抽离出公共字段到基类,然后各自继承基类就可以实现复用了。data class可以借鉴问题1的解决方法来实现。
open class Person(
var age: Int? = 0,
var name: String? = "lyx",
val sex: Boolean? = false
)
data class Student(val score: Int) : Person()
4.kotlin的反射依赖
如果项目中使用的fastJson,需要配合kotlin反射依赖才能顺利解析。"org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
匹配好自己的kotlin版本即可。
添加混淆配置:
-keepattributes *Annotation*
-keep class kotlin.** { *; }
-keep class org.jetbrains.** { *; }
必加的依赖,否则一堆问题。