在Kotlin中,编写泛型非内联函数时,x is T会因类型擦除而引发编译器错误.

fun <T> example(foo: Any, bar: T) {
    if (foo is T) { // compile error
        // ...
    }
}

然而,x as? T是完全好的,它似乎(虽然抛出通常的"未经判断的铸造"警告).为什么编译器不能用(x as? T) != null替换x is T?这两者之间有什么区别吗?

fun <T> example(foo: Any, bar: T) {
    if ((foo as? T) != null) { // no compile error
        // ...
    }
}

推荐答案

这在文件Generics type checks and casts中有解释

由于类型擦除,没有通用的方法来判断泛型类型的实例是否是在运行时使用某些类型参数创建的,编译器禁止此类IS判断,如INTS IS LIST或LIST IS T(类型参数).

解释了为什么不允许使用is. 和

... 泛型函数调用的类型参数也只在编译时判断.在函数体内,类型参数不能用于类型判断,类型转换为类型参数(foo为T)是unchecked

声明未选中foo as? T,就像foo as? Any一样.

我们可以通过运行下面的命令来验证这一点

public fun <T> asExample(foo: Any, bar: T): Boolean {
  if ((foo as? T) != null) { // no compile error
    return true
  }
  return false
}

public fun main() {
  println(asExample("A", "B"))
  println(asExample("A", 0))
}

它将打印

true
true

相关:What is difference between "as" and "is" operator in Kotlin?

Kotlin相关问答推荐

在Kotlin Jetpack中重用下拉菜单

为什么 Kotlin 中没有 init 块的注释

从 Kotlin 的父类获取函数注解

为什么使用 return instance ?: synchronized(this) { instance ?: PreferenceParameterState(context) } 时无法获得单例?

Kotlin 获取继承类的默认 hashCode 实现

按钮无法在 Android Studio 上打开新活动

Kotlin 协程按顺序执行,但仅在生产机器上执行

使用纯 Kotlin 函数作为 Junit5 方法源

如何在 Kotlin for Android 上使用setTextColor(hexaValue),

如何在 Android 的 Fragment 中使用 setUserVisibleHint

参考 Kotlin 中的 Java 接口静态字段

为什么 android studio 不为所有安全参数生成代码?

IntelliJ 不会根据 ktlint 的期望对 Kotlin 导入进行排序

如何从 Java 中隐藏 Kotlin 的 lateinit var 支持字段?

零安全的好处

Kotlin的BiMap/2-way hashmap

TypeConverter()在Android的TypeConverter错误中具有私有访问权限

具有泛型param的Kotlin抽象类和使用类型param的方法

Kotlin中对象和数据类的区别是什么?

使用 Kotlin 按字母对数组进行排序