首页 > 解决方案 > 为什么 check()、require() 和 assert() 不会产生智能转换?

问题描述

考虑以下代码片段:

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
    }
}

虽然check()两者require()都有

contract {
    returns() implies value
}

在他们的身体里,上面的代码仍然没有编译,迫使我使用?.

s?.length

!!

s!!.length

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

标签: kotlin

解决方案


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

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

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

我在 Kotlin 论坛上找到了这篇文章,问你到底是什么人。联系人存在了很长时间,但这篇文章也支持了我最初的假设:虽然联系人存在,但他们还没有准备好。如第二篇文章所述,有效禁用。这就是智能投射不起作用的原因。

然而,在 Kotlin 1.3 中,合约被释放了。如果您升级,您会发现它确实有效(至少对我有效)。


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


推荐阅读