Kotlin绑定的类参考和泛型

时间:2018-08-15 13:08:27

标签: android generics kotlin

我要改用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)
    }

Compiler Error

AFAIK,自1.1(https://kotlinlang.org/docs/reference/reflection.html#bound-class-references-since-11)以来允许此呼叫,那么我错过了什么?

2 个答案:

答案 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参数传递