Gson与Kotlin碰撞出一个不安全的操作

原因是我们Person没有提供默认的构造方法,Gson在没有找到默认构造方法时,它就直接通过Unsafe的方法,绕过了构造方法,直接构建了一个对象。

到这里,我们收获了:

Gson是如何构建对象的?

我们在写需要Gson转化为对象的类的时候,一定要记得有默认的构造方法,否则虽然不报错,但是很不安全!

我们了解到了还有这种Unsafe黑科技的方式构造对象。

4.1、使用 data class 没有设置无参构造函数

在 Kotlin 中,不需要自己动手去写一个 JavaBean,可以直接使用 DataClass,使用 DataClass 编译器会默默地帮我们生成一些函数。例如:

data class Person(var name: String, var age: Int) {}

这个Bean是用于接收服务器数据,通过Gson转化为对象的。例如:

val gson = Gson() val person = gson.fromJson<Person>("{"age":"12"}", Person::class.java) println(person.name)

我们传递了一个json字符串,但是没有包含key为name的值,并且注意:

在Person中name的类型是String,也就是说是不允许name=null的

输出结果:

null

是不是有些奇怪,感觉意外绕过了Kotlin的空类型检查。那么是什么原因导致的呢?

原因是:Person在被转Java代码时,只会生成一个包含两个参数的构造方法,没有提供默认的构造方法。Gson在通过反射创建对象时,会优先尝试获取无参构造函数。如果没有找到无参构造函数时,它就直接通过Unsafe的方法,绕过了构造方法,直接构建了一个对象。

因此我们在使用 data class,在遇到上面类似需求的时候,最好提供一个无参构造方法。

data class GsonDataTest(val name: String, val gender: String) {

constructor(): this(name = "",gender = "")

override fun toString(): String {

return "GsonDataTest(name='$name', gender='$gender')"

}

}

var data:String? = null

var testData = Gson().fromJson<GsonDataTest>(data, GsonDataTest::class.java)

DebugLog.d("aaaaaa", "$testData")

data = ""

testData = Gson().fromJson<GsonDataTest>(data, GsonDataTest::class.java)

DebugLog.d("aaaaaa", "$testData")

data = "{\"name\":\"aa\"}"

testData = Gson().fromJson<GsonDataTest>(data, GsonDataTest::class.java)

DebugLog.d("aaaaaa", "$testData")

data = "{\"name\":\"aa\", \"gender\":\"aa\"}"

testData = Gson().fromJson<GsonDataTest>(data, GsonDataTest::class.java)

DebugLog.d("aaaaaa", "$testData")
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容