天天看點

fread傳回值為0_談談Kotlin:Kotlin每一行代碼都有傳回值

一、

?:

+

let

實作的

if-else

這周在網上沖浪的時候,看到了這麼一T個讨論:“Elvis運算符與return組合的語句,在return前增加邏輯,如何寫得優雅?”,裡面提到一個「**使用

let

文法糖結合

?:

運算符實作

if-else

**」的示例:

```

account?.let {

it.hello()

it.name = "Hello"

} ?: run {

logger.error("account is null")

}

```

二、這裡藏着一個坑

乍一看,這種寫法很新穎很有創意,但實際上

let

文法糖後接

?:

這種做法是有問題的。

看下

let

文法糖的函數聲明:

public inline fun <T, R> T.let(block: (T) -> R): R

fread傳回值為0_談談Kotlin:Kotlin每一行代碼都有傳回值

結合實作,可以看到,

let

會在

block

執行完後,傳回block的傳回值。

而Kotlin和Java不同,在Kotlin裡每一行代碼都是表達式,也就是說每一行代碼執行完畢後都有一個傳回值。

接下來考慮如下例子:

```kotlin

// 例1:可空變量為空

val nullVal: Any? = null

nullVal?.let {

println("[nullVal] not null code block")

null

} ?: run {

println("[nullVal] null code block")

}

// 例2:可空變量為非空

val notnull: Any? = Any()

notnull?.let {

println("[notnull] not null code block")

null

} ?: run {

println("[notnull] null code block")

}

```

會得到如下輸出:

```

[nullVal] null code block

[notnull] not null code block

[notnull] null code block

```

例2的輸出顯然是不符合預期的。

在文章一開始的那個例子裡,由于

it.name = "Hello"

的傳回值是

Unit

,是一個非空的值,是以能夠如預期,呈現出和

if-else

等價的效果,但這裡實際上會留下一個隐藏的坑。

寫代碼的時候,肯定不會寫出我上面舉的例子那麼傻的代碼,考慮如下變種:

```kotlin

fun test_let() {

val nullable: Any? = null

nullable?.let {

println("[nullable] not null code block")

maybeReturnNull(0)

} ?: run {

println("[nullable] null code block")

}

val notnull: Any? = Any()

notnull?.let {

println("[notnull] not null code block")

maybeReturnNull(0)

} ?: run {

println("[notnull] null code block")

}

}

private fun maybeReturnNull(count: Int): Any? = if (count % 2 == 0) null else Any()

```

一旦命中這樣的坑,查起來挺費勁的 QAQ

掉過這樣的坑後,就會發現樸素的

if (xxx != null)

的寫法其實是最可愛的。

三、Tips

介紹一個小技巧:

IDEA編輯器提供了快速判空的模闆,在變量後輸入

.nn

回車。

fread傳回值為0_談談Kotlin:Kotlin每一行代碼都有傳回值

就能收獲如下代碼。

fread傳回值為0_談談Kotlin:Kotlin每一行代碼都有傳回值

PS:

nn

notnull

的縮寫,輸入

.notnull

也有同樣的功效。

繼續閱讀