为什么 check()、require() 和 assert() 不会产生智能转换?

Bas*_*ass 7 kotlin

考虑以下代码片段:

object C {
    @JvmStatic
    fun main(vararg args: String) {
        val s: String? = null
        check(s != null) {
            "The string is null"
        }
        require(s != null) {
            "The string is null"
        }
        assert(s != null) {
            "The string is null"
        }
        s.length
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然check()require()都有

contract {
    returns() implies value
}
Run Code Online (Sandbox Code Playgroud)

在他们的体内,上面的代码仍然无法编译,迫使我使用?.

s?.length
Run Code Online (Sandbox Code Playgroud)

或者!!

s!!.length
Run Code Online (Sandbox Code Playgroud)

为什么上面的代码中没有执行智能转换?

Zoe*_*Zoe 7

我不久前回答过一个相关问题,assert关于和之间的区别require。TL;DR:assert不能保证抛出异常,但require确实会抛出异常。在 Kotlin 1.3 中,它还使用契约,这意味着如果方法返回,编译器就知道该语句是正确的,并且可以应用智能转换(如果适用)。

这解释了为什么assert不这样做;从断言返回并不意味着该陈述是正确的。使用您拥有的代码,除非为真,否则它不会抛出异常ea。即使使用 1.3,断言也不会触发智能转换。

check并且require两者都会在 1.3 及更高版本上触发智能转换(因为合约),而断言则不会(没有合约,并且不能保证如果条件失败它实际上会抛出异常)。

我在 Kotlin 论坛上找到了这篇文章,询问您到底是什么。这些合同已经存在了相当长的一段时间,但这篇文章也支持了我最初的假设:虽然合同已经存在,但它们还没有准备好。正如第二篇文章提到的那样,实际上已被禁用。这就是智能转换不起作用的原因。

然而,在 Kotlin 1.3 中,合约被发布了。如果您升级,您会发现它确实有效(至少对我来说是这样)。


1.3-M2中添加了完整的合约支持,它是 1.3 的预发布版本。