【问题标题】:is-check or a cast that involves the non-generic part of the typeis-check 或涉及类型的非泛型部分的强制转换
【发布时间】:2020-01-28 20:55:51
【问题描述】:

我在阅读 Kotlin 参考资料时遇到了几个问题:

在“类型擦除和泛型类型检查”中,它提到:

当您已经静态检查了实例的类型参数时(在编译时 time),您可以进行涉及类型的非泛型部分的 is-check 或强制转换。笔记 在这种情况下,尖括号被省略了

他们举了一个例子:

fun handleStrings(list: List<String>) {
    if (list is ArrayList) {
        // `list` is smart-cast to `ArrayList<String>`
    }
}

Q1:我测试自己

val a = mutableListOf(1, 2, 3)
val b = listOf(1, 2, 3)
println(a is List)   //error, should use List<*>
println(b is MutableList)   //can compile

我不明白为什么他们得到不同的结果。

Q2:我发现我无法使用从 List 到 ArrayList 的智能转换

println(listOf(1, 2, 3) is ArrayList)  //false
println(listOf(1, 2, 3) is MutableList)  //true

我记得,listOf() 是由 Kotlin 中的 ArrayList 实现的,它在 Arrays.java 中调用 asList,它返回一个 ArrayList。 那么,为什么 listOf() 不能智能转换为 ArrayList?

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    A1:在第一种情况下,您从子类转换为超类。这没有任何意义,因为子类的实例总是可以用作超类的实例而无需强制转换:

    val a: MutableList<Int> = mutableList(1, 2, 3)
    val b: List<Int> = a
    

    因此,Kotlin 编译器没有实现用于楼上投射的通用智能投射,而是使用需要星形投影的默认投射规则。

    在第二种情况下,您从超类转换为子类,因此它按预期工作。

    A2:有两个不同的ArrayList 类。尝试运行这段代码:

    println(listOf(1, 2, 3)::class)
    println(ArrayList<String>()::class)
    

    打印出来:

    class java.util.Arrays$ArrayList
    class java.util.ArrayList
    

    listOf 返回一个嵌套类 Arrays.ArrayList,而不是您通常使用的 ArrayList

    【讨论】:

    • 感谢您的回答!很有帮助!
    • 另外,listOf() 的确切返回类型未在文档中指定,可能是因为它将来可能会更改:例如,它可能会为空或非常小的列表返回特殊对象,或者它们可能会提出更高性能和/或真正不可变的实现。所以你不应该对确切的类型做出任何假设,或者以任何方式依赖它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 2014-02-04
    • 2021-09-11
    相关资源
    最近更新 更多