【问题标题】:Why can't I get the class of a generic parameter?为什么我不能得到泛型参数的类?
【发布时间】:2017-09-12 16:05:50
【问题描述】:

我有一个函数,它接受一个泛型类型的参数,我想访问它的类:

fun <T> test(t: T) {
    t::class
}

这会因为“类文字中的表达式具有可为空的类型”而失败。没关系,我理解(我可以使用Any? 作为我的T 和null 作为值)。
但是,如果我将其更改为保证 t 不为空,它仍然会失败并显示相同的错误消息:

fun <T> test(t: T) {
    t!!::class
}

t!!::class在什么情况下还能惹麻烦?
有没有办法在不使用 Any(或强制转换为 Any)的情况下获取课程?

【问题讨论】:

    标签: generics kotlin


    【解决方案1】:

    更改您的类型以指示它不可为空并且它应该可以工作。您可以通过指示T 需要扩展Any(而不是Any?)来做到这一点。

    fun <T : Any> test(t: T) {
        t::class
    }
    

    【讨论】:

    • 好的,很好。但是,在哪种情况下t!!::class 会有问题?
    • 不太确定。我玩过它,但并没有很好的解释,TBH。
    • @danielspaniol 请参阅:stackoverflow.com/questions/35602231/…,t!! 在答案的 cmets 中进行了讨论。
    【解决方案2】:

    首先,让我们修复它

    使泛型类型T不可为空:

    fun <T: Any> test(t: T) {
        println(t::class)
    }
    

    通过default,上限是Any?,而不是Any:

    "默认的上限(如果没有指定)是 Any?。尖括号内只能指定一个上限。如果同一个类型参数需要多个上限,我们需要一个单独的 where 子句。

    旁注:您错误地使用了!!

    “但是如果我把它改成保证 t 不为空……”

    这不是您在使用!! 时所做的事情。相反,您是在告诉编译器:我不希望您检查我的类型是否可以为空。继续并调用该函数。我不怕NullpointerExceptions。

    "在什么情况下 t!!::class 还能造成麻烦?"

    正如我上面所说,当您调用!! 的类型是 null 时,它会引起麻烦。然后,和 Java 一样,NPE 会在运行时抛出。

    【讨论】:

    • 我会抛出一个 NPE 以防 null 是想要的,因为 null 很可能是一个错误,所以我认为这正是想要的。当然,这暴露了真正的问题,首先使用 nullable。 Kotlin 的好处在于它在早期就暴露了空值的入口点。无论如何,Kotlin 并没有解决 null 的潜在问题,它只会让它们更好地使用。
    • 我不明白为什么默认上限可以为空 - Any?,如果它只是 Any 会更简单。当有一个基类被参数化Type&lt;T : Any&gt; 然后它被用来构建子类型 - SubType&lt;Type&lt;T : Any&gt;&gt; 时,它变得相当不方便。这种方法需要覆盖每个子类的上限。
    【解决方案3】:

    您想使用reified 类型。您可以了解更多关于具体类型参数here 或here。代码:

    inline fun <reified T : Any> test(t: T) {
        println(T::class)
    }
    

    【讨论】:

    • 你不需要这样做。你也可以像他那样把类传给函数
    • 你是对的。但我不确定他是想获取该特定实例的类,还是从类型中获取类。就个人而言,我从未使用过::class 函数引用来访问实体的类型。
    猜你喜欢
    • 2016-05-14
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 2020-07-01
    • 1970-01-01
    相关资源
    最近更新 更多