ZetCode

Kotlin !is 关键字

最后修改于 2025 年 4 月 19 日

Kotlin 的类型检查系统提供了强大的运算符来验证运行时的类型。!is 关键字用于负类型检查。本教程通过实际示例深入探讨了 !is 关键字。

基本定义

Kotlin 中的 !is 关键字是 is 运算符的否定形式。它检查一个对象是否不是特定类型的实例。与 is 一样,它在相应的代码块中启用智能类型转换。

基本 !is 检查

!is 最简单的用法是验证一个对象不是某种类型。当您想以不同的方式处理不同类型时,这很有用。

BasicNotIs.kt
package com.zetcode

fun main() {

    val obj: Any = 42
    
    if (obj !is String) {
        println("Object is not a String")
    }
}

在这里,我们检查 obj 是否不是 String。由于它是一个 Int,因此条件为真,并打印消息。这是 !is 最基本的用法。

!is 与智能类型转换

!is 检查之后,Kotlin 将对象智能地类型转换为相应块中的否定类型。这使您可以安全地使用其他类型的方法。

SmartCastNotIs.kt
package com.zetcode

fun printIfNotString(obj: Any) {
    if (obj !is String) {
        println("Value is ${obj} and type is ${obj.javaClass.simpleName}")
    }
}

fun main() {

    printIfNotString(123) // Output: Value is 123 and type is Integer
    printIfNotString(true) // Output: Value is true and type is Boolean
}

在此示例中,在 !is String 检查之后,Kotlin 知道 obj 不是 String。然后,我们可以安全地访问实际类型的属性,例如 javaClass

!is 在 When 表达式中

!is 运算符在 when 表达式中运行良好,以处理多种类型的情况。它有助于创建详尽的类型检查逻辑。

WhenNotIs.kt
package com.zetcode

fun describeType(obj: Any): String {
    return when (obj) {
        is String -> "String of length ${obj.length}"
        !is Number -> "Not a number"
        else -> "Number with value ${obj.toDouble()}"
    }
}

fun main() {

    println(describeType("Hello")) // String of length 5
    println(describeType(true)) // Not a number
    println(describeType(42)) // Number with value 42.0
}

此示例显示了如何在 when 表达式中使用 !is。在 String 检查之后,!is Number 分支捕获所有非数字类型。

!is 与空值检查

!is 运算符可以与空值检查结合使用,以创建更复杂的条件。这在处理可空类型时特别有用。

NullCheckNotIs.kt
package com.zetcode

fun processValue(value: Any?) {
    if (value !is String? || value == null) {
        println("Not a string or null")
    } else {
        println("String length is ${value.length}")
    }
}

fun main() {

    processValue(null) // Not a string or null
    processValue(123) // Not a string or null
    processValue("Kotlin") // String length is 6
}

在这里,我们将 !is 与空值检查结合使用,以处理非字符串类型和空值。智能类型转换确保我们可以在 else 分支中安全地访问 String 属性。

!is 在泛型函数中

!is 运算符可用于泛型函数,以对泛型参数执行类型检查。这需要具体化的类型参数。

GenericNotIs.kt
package com.zetcode

inline fun <reified T> isNotType(obj: Any): Boolean {
    return obj !is T
}

fun main() {

    println(isNotType<String>("Hello")) // false
    println(isNotType<Int>("World")) // true
    println(isNotType<List<*>>(emptyList<String>())) // false
}

此泛型函数使用 !is 和具体化的类型参数来检查对象是否不是类型 T。具体化的参数在运行时保留类型信息。

!is 与集合

!is 运算符可用于检查集合类型或根据类型过滤集合。这在处理异构集合时很有用。

CollectionNotIs.kt
package com.zetcode

fun main() {

    val mixedList: List<Any> = listOf(1, "two", 3.0, "four", 5)
    
    val nonStrings = mixedList.filter { it !is String }
    println("Non-string elements: $nonStrings")
    
    if (mixedList !is List<String>) {
        println("List contains non-string elements")
    }
}

在这里,我们使用 !is 从混合列表中过滤掉 String 元素。我们还检查整个列表是否不是 List<String>。这两种用法都演示了 !is 与集合的使用。

!is 在类层次结构中

!is 运算符在处理类层次结构时特别有用。它有助于确定一个对象何时不是特定子类。

HierarchyNotIs.kt
package com.zetcode

open class Animal
class Dog : Animal() {
    fun bark() = "Woof!"
}
class Cat : Animal() {
    fun meow() = "Meow!"
}

fun makeSound(animal: Animal) {
    if (animal !is Dog) {
        println("Not a dog")
        if (animal is Cat) {
            println(animal.meow())
        }
    } else {
        println(animal.bark())
    }
}

fun main() {

    makeSound(Dog()) // Woof!
    makeSound(Cat()) // Not a dog \n Meow!
}

此示例显示了类层次结构中的 !is。我们首先检查动物是否不是 Dog,然后处理其他情况。智能类型转换允许在适当的块中调用 Cat 特定的方法。

!is 运算符的最佳实践

来源

Kotlin 类型检查和类型转换文档

本教程深入介绍了 Kotlin 的 !is 关键字,展示了它在各种场景中的用法,包括智能类型转换、when 表达式和泛型。如果使用得当,!is 运算符是用于类型安全的 Kotlin 代码的强大工具。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有多年的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我写了超过 1400 篇文章和 8 本电子书。我拥有超过八年的编程教学经验。

列出 所有 Kotlin 教程