Kotlin 具体化的泛型没有按计划保留类型
Kotlin reified generics does not keep the type as planned
我正在创建一个类似于 Gson 的类似 TypeToken
的系统,但我偶然发现了一些我不理解的东西。
此代码的目的是只有一个 TypeReference
class 和一个可以包含多个参数的通用参数。 class 将使用 inline
函数创建,这样用户就不需要知道 Holder
class.
请考虑以下代码:
package testing
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
abstract class TypeReference<T : Holder> {
val type: Type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
override fun toString(): String {
return type.typeName
}
}
inline fun <reified T : Holder> create() = object : TypeReference<T>() {}
inline fun <reified WHAT> createSingle() = object : TypeReference<Single<WHAT>>() {}
class Foo
interface Holder
interface Single<T> : Holder
fun main(args: Array<String>) {
println(create<Single<HashMap<Int, String>>>())
println(create<Single<Foo>>())
println(createSingle<HashMap<Int, String>>())
println(createSingle<Foo>())
}
这是输出:
testing.Single<java.util.HashMap<java.lang.Integer, java.lang.String>>
testing.Single<testing.Foo>
testing.Single<WHAT>
testing.Single<WHAT>
在我看来,好像 Single<WHAT>
(对不起那个通用名称)没有得到 'truly' 内联,并且生成了一些中间名称。
我也查看了 docs,但没有找到相关示例。
如何创建我最初打算做的事情?为什么会这样?
编辑:
我想创建一个问题,但他们已经知道了。
发布了一个非常相似的问题 here which is said to be a duplicated of this。您也可以在后者link中投票。
供日后参考:此处使用Kotlin 1.2.50
。
我反编译了这段代码,发现两个函数有些不同
private static final TypeReference create() {
Intrinsics.needClassReification(); <---- here
return (TypeReference)(new TypeReference() {
});
}
private static final TypeReference createSingle() {
return (TypeReference)(new TypeReference() {
});
}
手动添加这段代码,效果很好。不太了解这个,没找到文献
inline fun <reified WHAT > createSingle() = Intrinsics.needClassReification().let {
object : TypeReference<Single<WHAT>>() {}
}
结果:
Single<java.util.HashMap<java.lang.Integer, java.lang.String>>
Single<Foo>
Single<java.util.HashMap<java.lang.Integer, java.lang.String>>
Single<Foo>
我正在创建一个类似于 Gson 的类似 TypeToken
的系统,但我偶然发现了一些我不理解的东西。
此代码的目的是只有一个 TypeReference
class 和一个可以包含多个参数的通用参数。 class 将使用 inline
函数创建,这样用户就不需要知道 Holder
class.
请考虑以下代码:
package testing
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
abstract class TypeReference<T : Holder> {
val type: Type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
override fun toString(): String {
return type.typeName
}
}
inline fun <reified T : Holder> create() = object : TypeReference<T>() {}
inline fun <reified WHAT> createSingle() = object : TypeReference<Single<WHAT>>() {}
class Foo
interface Holder
interface Single<T> : Holder
fun main(args: Array<String>) {
println(create<Single<HashMap<Int, String>>>())
println(create<Single<Foo>>())
println(createSingle<HashMap<Int, String>>())
println(createSingle<Foo>())
}
这是输出:
testing.Single<java.util.HashMap<java.lang.Integer, java.lang.String>>
testing.Single<testing.Foo>
testing.Single<WHAT>
testing.Single<WHAT>
在我看来,好像 Single<WHAT>
(对不起那个通用名称)没有得到 'truly' 内联,并且生成了一些中间名称。
我也查看了 docs,但没有找到相关示例。
如何创建我最初打算做的事情?为什么会这样?
编辑:
我想创建一个问题,但他们已经知道了。
发布了一个非常相似的问题 here which is said to be a duplicated of this。您也可以在后者link中投票。
供日后参考:此处使用Kotlin 1.2.50
。
我反编译了这段代码,发现两个函数有些不同
private static final TypeReference create() {
Intrinsics.needClassReification(); <---- here
return (TypeReference)(new TypeReference() {
});
}
private static final TypeReference createSingle() {
return (TypeReference)(new TypeReference() {
});
}
手动添加这段代码,效果很好。不太了解这个,没找到文献
inline fun <reified WHAT > createSingle() = Intrinsics.needClassReification().let {
object : TypeReference<Single<WHAT>>() {}
}
结果:
Single<java.util.HashMap<java.lang.Integer, java.lang.String>>
Single<Foo>
Single<java.util.HashMap<java.lang.Integer, java.lang.String>>
Single<Foo>