Kotlin中的单个感叹号

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

54054 次浏览

它们被称为平台类型,它们的意思是Kotlin不知道该值是否可以为null,它由你来决定它是否为空。

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

这就是为什么我们采取了一种激进的方法,使Kotlin的类型系统在涉及Java互操作时更加轻松:现在来自Java的引用具有特殊标记的类型——芬兰湾的科特林的博客

它是平台类型的符号:

T!表示“TT?

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

平台类型符号

[…]

T!意思是“;__abc1”;[…]

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

我已经见过几次了,尤其是在使用Java api时

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

为了允许空值,我们可以声明一个变量为可空字符串,写入 字符串?: < / p >
var b: String? = "abc"
b = null // ok

[…]

b?.length

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

节选自Kotlin中的平台类型:

除了显式地指定一个类型为可选(例如Person?), Kotlin还为我们提供了另一个野兽,称为Platform Type,通过放置一个感叹号来代替(例如Person!)。创建这个概念是出于兼容性的考虑,当从Java这样的空不安全平台访问代码时。通常情况下,当使用Java库时,许多方法返回SomeType!,因为Kotlin编译器无法推断结果是否为空。

例如:

(Mutable)Collection<T>!

只意味着:“Java集合的T可能是可变的或不是,可能是空的或不是”。

希望这能有所帮助。

平台类型

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

例子:

Nullable信息:Nullable类型

Java中的@Nullable String被Kotlin认为是String?

Non-null Information:非空类型

Java中的@NotNull String被Kotlin认为是String

无信息:平台类型

在Java中没有注释的String被Kotlin认为是String!


如何处理平台类型?

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

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


继承和平台类型

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

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

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

?:我不知道它是否为空。
小心点!这可能是空的。
!!:小心,是的,我知道。