Kotlin reified仿制药没有按计划保留类型

and*_*ras 12 generics kotlin kotlin-reified-type-parameters

我正在创建一个TypeToken类似于Gson的类似系统,我偶然发现了一些我不理解的东西.

这段代码的意图是只有一个TypeReference带有一个泛型参数的类可以容纳多个.该类将使用inline函数创建,这样用户无需知道Holder该类.

请考虑以下代码:

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>())
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

testing.Single<java.util.HashMap<java.lang.Integer, java.lang.String>>
testing.Single<testing.Foo>
testing.Single<WHAT>
testing.Single<WHAT>
Run Code Online (Sandbox Code Playgroud)

看起来好像Single<WHAT>(通用名称的sry)没有"真正"内联并且生成了一些中间名称.

我也查看了文档,但我没有找到关于此的示例.

如何创建我最初打算做的事情?为什么会这样?

编辑.:

我想创建一个问题,但他们已经知道了这一点.

这里发布一个非常类似的问题,据说这是一个重复的问题.您也可以在后一个链接中投票.

供将来参考:Kotlin 1.2.50此处使用.

use*_*210 5

我反编译这段代码,发现两个函数之间有些不同

private static final TypeReference create() {
  Intrinsics.needClassReification();                 <---- here
  return (TypeReference)(new TypeReference() {
  });
}

private static final TypeReference createSingle() {
  return (TypeReference)(new TypeReference() {
  });
}
Run Code Online (Sandbox Code Playgroud)

并手动添加此代码,工作正常。对这个不太了解,没有找到文档。

inline fun <reified WHAT > createSingle() = Intrinsics.needClassReification().let {
    object : TypeReference<Single<WHAT>>() {}
}
Run Code Online (Sandbox Code Playgroud)

结果

Single<java.util.HashMap<java.lang.Integer, java.lang.String>>

Single<Foo>

Single<java.util.HashMap<java.lang.Integer, java.lang.String>>

Single<Foo>
Run Code Online (Sandbox Code Playgroud)