我要改用Android的Kotlin,但我一直在努力理解泛型和绑定类引用的行为。 在Java中,我可以使用Moshi的lib通过以下行来序列化对象:
Moshi moshi = new Moshi.Builder().build();
String string = moshi.adapter(CredentialsResponse.class).toJson(body);
在科特林:
val moshi = Moshi.Builder().build()
var string = moshi.adapter(CredentialsResponse::class.java).toJson(body)
如果我想从实例中获取该类,我发现了两个选项,但是一个不起作用,并且我不明白为什么: 这段代码有效:
fun testStack(body: CredentialsResponse) {
val moshi = Moshi.Builder().build()
var string = moshi.adapter(body.javaClass).toJson(body)
}
但是此代码显示类型不匹配错误
fun testStack(body: CredentialsResponse) {
val moshi = Moshi.Builder().build()
var string = moshi.adapter(body::class.java).toJson(body)
}
AFAIK,自1.1(https://kotlinlang.org/docs/reference/reflection.html#bound-class-references-since-11)以来允许此呼叫,那么我错过了什么?
答案 0 :(得分:2)
正如@AlexeySoshin所指出的,区别在于未绑定的类引用Foo::class
的类型与所引用类KClass<Foo>
的确切类型相同,而绑定的类的引用则由{ {1}}投影:out
。
存在这种差异的强烈原因。当您通过类的名称引用一个类时,可以确保该引用所评估的类标记准确地指定了所引用的类型。
但是,当您获得类型为KClass<out Foo>
的表达式的绑定类引用时,该表达式可以求值为Foo
的子类型的实例,并且类型标记的正确类型为{ {1}},确切地意味着实际类型参数可以是Foo
或其子类型。
有关绑定和未绑定类引用之间差异的另一详细说明,请参见以下答案:(link)
答案 1 :(得分:1)
两者之间有细微的差别:
class K
val javaClass: JsonAdapter<K> = moshi.adapter(body.javaClass)
val classJava: JsonAdapter<out K> = moshi.adapter(body::class.java)
请注意,body::class.java
被标记为out
通过调用moshi.adapter(body::class.java).toJson(body)
,您尝试将body
作为in
参数传递