我正在参与「启航计划」
Kotlin是由JetBrains开发的针对JVM、Android和浏览器的静态编程言语,是Android的官方言语。Kotlin拥有较多高档而又简练的语法特性,提升了咱们的开发效率,减少了代码量。
在开端之前先看一块代码段:
fun printLength(str: String? = null) {
println(str?.length) // 1
if (!TextUtils.isEmpty(str)) { // 2
println(str?.length)
}
if (!str.isNullOrEmpty()) { // 3
println(str.length)
}
}
为何1和2两处需要增加问号?,而3处则不需要,为什么呢?直接见源码,这儿的isNullOrEmpty其实是Kotlin中Strings.kt的扩展办法:
@kotlin.internal.InlineOnly
public inline fun CharSequence?.isNullOrEmpty(): Boolean {
contract {
returns(false) implies (this@isNullOrEmpty != null)
}
return this == null || this.length == 0
}
你会发现里边应用了contract,咱们不妨照着用contract写一个:
@ExperimentalContracts
inline fun String?.isNotNullWithContract(): Boolean {
contract {
returns(true) implies (this@isNotNullWithContract != null)
}
return this != null && this.isNotEmpty()
}
那咱们运用一下看看:
class CheckNullTest {
@ExperimentalContracts
inline fun String?.isNotNullWithContract(): Boolean {
contract {
returns(true) implies (this@isNotNullWithContract != null)
}
return this != null && this.isNotEmpty()
}
@ExperimentalContracts
fun printLength(str: String? = null) {
println(str?.length) // 1
if (!TextUtils.isEmpty(str)) { // 2
println(str?.length)
}
if (!str.isNullOrEmpty()) { // 3
println(str.length)
}
if (str.isNotNullWithContract()) { // 4
println(str?.length)
}
}
}
你会发现4处仍是需要用问号?,怎样仿着写无效,contract没有生效?看contract源码:
/**
* Specifies the contract of a function.
*
* The contract description must be at the beginning of a function and have at least one effect.
*
* Only the top-level functions can have a contract for now.
*
* @param builder the lambda where the contract of a function is described with the help of the [ContractBuilder] members.
*
*/
@ContractsDsl
@ExperimentalContracts
@InlineOnly
@SinceKotlin("1.3")
@Suppress("UNUSED_PARAMETER")
public inline fun contract(builder: ContractBuilder.() -> Unit) { }
见注释中Contracts are allowed only for top-level functions, 原来是运用的姿态有问题,那换个姿态再来一次:
@ExperimentalContracts
inline fun String?.isNotNullWithContract(): Boolean {
contract {
returns(true) implies (this@isNotNullWithContract != null)
}
return this != null && this.isNotEmpty()
}
class CheckNullTest {
@ExperimentalContracts
fun printLength(str: String? = null) {
println(str?.length) // 1
if (!TextUtils.isEmpty(str)) { // 2
println(str?.length)
}
if (!str.isNullOrEmpty()) { // 3
println(str.length)
}
if (str.isNotNullWithContract()) { // 4
println(str.length)
}
}
}
此刻发现终于和Kotlin中Strings.kt的扩展办法isNullOrEmpty()表现一致了,不用增加问号?了。
contract(契约)是一种 Kotlin 面向编译器约定的一种规矩,它帮助编译器更加智能地识别某些需要特定的代码条件,为代码创建更加友爱的上下文关联环境。 Kotlin 在 1.3 版本以实验室功能的方式开端引进 contract, 截止至当前 Kotlin 最新版本 1.6.10,contract 办法仍然增加有 @ExperimentalContracts 注解。
常见标准库函数run,also,with,apply,let,每个里边都用到contract契约:
//以apply函数举例,其他函数同理
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}