【问题标题】:Single exclamation mark in KotlinKotlin 中的单个感叹号
【发布时间】:2021-10-05 06:23:30
【问题描述】:

在 Kotlin 中,一个感叹号是什么意思?我见过几次,尤其是在使用 Java API 时。但我在文档和 StackOverflow 上都找不到它。

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    它们被称为 platform types,它们意味着 Kotlin 不知道该值是否可以为 null,由您决定它是否可以为空。

    简而言之,问题在于来自 Java 的任何引用都可能为空,而 Kotlin 在设计上是空安全的,它强制用户对每个 Java 值进行空检查,或者使用安全调用 (?.)或非空断言 (!!)。这些在纯 Kotlin 世界中非常方便的功能,当您不得不在 Kotlin/Java 环境中过于频繁地使用它们时,往往会变成一场灾难。

    这就是为什么我们在 Java 互操作方面采取了激进的方法并使 Kotlin 的类型系统更加宽松:现在来自 Java 的引用具有特殊标记的类型 -- Kotlin Blog

    【讨论】:

      【解决方案2】:

      这是platform types的符号:

      T! 表示“TT?

      【讨论】:

      • 为什么不T 表示“T!T?
      • T!表示不可为空,T?表示可以为空。为什么 Kotlin 不这样做...
      • 因为显而易见的原因,最好的默认值是“不可为空的”,并且将默认值设为最短的类型签名是一个很好的设计。因此T 被设为“不可为空”,其余部分或多或少是任意的
      【解决方案3】:

      平台类型

      以单个感叹号! 结尾的类型名或类名在Kotlin 中称为平台类型。当您使用不包含可空性信息的旧 Java 代码在 Kotlin 中工作时,您会发现它们。

      例子:

      可空信息:可空类型

      @Nullable String 在 Java 中被 Kotlin 视为 String?

      非空信息:非空类型

      Java 中的@NotNull String 被 Kotlin 视为String

      无信息:平台类型

      在 Java 中没有注解的String 被 Kotlin 视为 String!


      平台类型如何处理?

      您可以使用可空或非空的平台类型。编译器将允许您调用此类型的所有方法。如何使用它们是您的责任。如果您知道该值可以为 null,则应在对其调用方法之前将其与 null 进行比较。如果你知道它不为空,你可以直接使用它,但就像在 Java 中一样,如果你对可空性的假设是错误的,你会得到异常。

      请注意,您不能在 Kotlin 代码中声明平台类型,它们仅来自 Java 代码。


      继承和平台类型

      在 Kotlin 代码中重写 Java 方法时,您可以选择将参数和返回类型声明为可空或非空。您需要明智地选择此选项,因为如果您决定将参数设为非 null,Kotlin 编译器会为这些非 null 参数生成非 null 断言。当你下次从 Java 访问这个 Kotlin 代码并传递一个 null 值时,你会得到异常。

      希望这有助于消除您对平台类型的所有疑虑。

      【讨论】:

        【解决方案4】:

        ! 表示的类型称为平台类型,它是一种来自Java的类型,因此很可能是null。这是 Kotlin 编译器在调用 Java 时默认推断的内容(对于最基本的情况,Java 方法可以是 annotated 来解决这个问题)。您应该将平台类型处理为 可为空 类型,除非您确定特定 API 永远不会返回 null。编译器允许将平台类型分配给可空和非空类型的变量。

        Notation for Platform Types

        [...]

        T! 表示“T or T?”[...]

        您可以将平台类型称为“unknown nullability 类型”。同样重要的是,您不能将感叹号类型用于您自己的类型,它不是 Kotlin 语法的一部分,它只是一个符号

        【讨论】:

        • 像“最有可能”这样的短语没有帮助
        【解决方案5】:

        我见过几次,尤其是在使用 Java API 时

        正如 s1m0nw1 所述,T! 表示 T or T?。下一个问题是:T? 是什么?这在https://kotlinlang.org/docs/reference/null-safety.html 中有很好的记录。 Kotlin 不允许某些元素为 null,例如String,不像Java

        为了允许空值,我们可以将变量声明为可空字符串,写成 字符串?:

        var b: String? = "abc"
        b = null // ok
        

        [...]

        b?.length 
        

        如果 b 不为 null,则返回 b.length,否则返回 null。这个表达式的类型是Int?

        【讨论】:

          【解决方案6】:

          我用有趣的解释来记住这些事情如下:

          ?:不知道是不是null。
          !:小心!这可能是空的。
          !!: 小心,是的,我知道。这始终不为空。

          【讨论】:

            【解决方案7】:

            摘自Platform Types in Kotlin

            除了将类型明确指定为可选(例如 Person?)之外,Kotlin 还向我们展示了另一个名为 Platform Type 的野兽,它通过放置一个感叹号来指定(例如 @ 987654324@)。当从 Java 等不安全的 null 平台访问代码时,出于兼容性原因创建了此概念。通常情况下,在使用 Java 库时,许多方法返回 SomeType!,因为 Kotlin 编译器无法推断结果是否可为空。

            例如:

            (Mutable)Collection<T>! 
            

            仅表示以下含义:“T 的 Java 集合可能是可变的或不是的,可能是可空的或不可为空的”。

            希望这会有所帮助。

            【讨论】:

              猜你喜欢
              • 2022-01-23
              • 1970-01-01
              • 2020-07-25
              • 2012-03-28
              • 2022-01-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多