Mou*_*usa 2 immutability gson kotlin
val
根据设计,Kotlin的属性是不可改变的.初始化后,它们应该是固定的且不可更改的.
但是,我偶然发现Gson
能够修改这些属性.
考虑这个例子:
//Entity class:
class User {
val name: String = ""
val age: Int = 0
}
Run Code Online (Sandbox Code Playgroud)
由于name
和age
被定义为val
并被初始化为空字符串和零,它们必须保持不变并且永远不会改变.
但是,此测试成功:
fun main() {
val json = "{\"name\":\"Mousa\",\"age\":30}"
val user = Gson().fromJson<User>(json, User::class.java)
assert(user.name == "Mousa")
assert(user.age == 30)
print("Success")
}
Run Code Online (Sandbox Code Playgroud)
使用此功能可使代码更清晰.因为这些属性是由Gson修改的,并且不能被我们的其余代码修改.否则,我需要为Gson提供一些可变的支持字段,为其余代码提供一些不可变的属性.
我不知道这是"特征" Gson
还是"虫子".所以我的问题是:我们可以依赖于此,或者此行为可能会在以后发生变化吗?
小智 5
如果运行javap -p User.class
,则会得到以下输出:
public final class q54491286.User {
private final java.lang.String name;
private final int age;
public final java.lang.String getName();
public final int getAge();
public q54491286.User();
}
Run Code Online (Sandbox Code Playgroud)
科特林不变性是对于那些(隐含的)声明的字段不会产生突变的方法支持private
和final
.除非你定义一个自定义类型的适配器,GSON,通过设计,既不使用也不存取存取器序列化和反序列化过程中分别设计为纯数据对象类(详见这里的使用领域VS干将,表示JSON中的元素部分).此外,Gson可以修改final
字段,这也是一个设计选择.
由于大量使用反射,不变性在Java中是相对的.例如,我可以使用反射轻松修改不可变(按设计)字符串,使其成为一种可变的(按意图):
final String s = "foo";
final Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set(s, new char[]{ 'b', 'a', 'r' });
System.out.println(s);
Run Code Online (Sandbox Code Playgroud)
这将产生bar
使用时,我java
从java version "1.8.0_191"
.没有不变性,他 - 他.
另一方面,如果您的类可以通过Gson类型的适配器策略以通用方式重新定义方法(Gson禁止重新定义Object
和JsonElement
类型适配器),您将能够编写一个禁止Kotlin生成的类的自定义反序列化器(通过kotlin.Metadata
注释检测到只读字段被反序列化(不确定它是否有好处).或者只是实现一个反序列化器,它将扫描JSON流/树中的非只读字段,并仅在构造具有User
不使用反射的合法构造函数的新对象时使用它们.
我不知道这是Gson的"特征"还是"Bug".
总结一下,这是一个功能.
所以我的问题是:我们可以依赖于此,或者此行为可能会在以后发生变化吗?
这很可能不会在Gson 2.x中发生变化.据我所知,没有任何计划发布重大更新,Gson 3.x等等.
归档时间: |
|
查看次数: |
51 次 |
最近记录: |