Kotlin常見問題和代碼

記錄Kotlin常見問題和代碼。

6. when代替OR智能轉換(20171122)

在網上看到一個問題是說有兩個方法,同名不同參數

fun foo(long: Long) {...}
fun foo(int: Int) {...}

然后現在有個變量是未定類型val someValue: Any = "0" // 0 or 0L,在使用foo方法的時候,然后他是這樣寫的,問說如何智能轉換,不要使用||

if (someValue is Int || someValue is Long) {
    foo(someValue)
}
// 或者這樣
if (someValue is Int)
    foo(someValue)
else if (someValue is Long)
    foo(someValue)

使用when來替代它

when (someValue) {
    is Long -> foo(someValue)
    is Int -> foo(someValue)
}

這樣就體現了Kotlin的智能轉換功能了

image
5. 同時符合untildownTo要求(20171025)

之前看到別人問了一個說想遞減同時又不包含結束值怎么寫? downTo 和 until 不能并存,截圖如下

image

滿足他

for (i in (0 until 10).reversed()) {
    println(i)
}

但是我不是很明白他這樣的需求,until又不能減掉中間的數,只能是區間的頭和尾,上面的需求擺明可以這樣寫,

for (i in (0 until 10).reversed()) {
    println(i)
}

為什么一定要用untildownTo結合呢???

image
4. 使用when表達式多個case符合條件,判斷要寫全

使用Kotlin的when表達式來判斷多個case符合條件,換成Java就是

switch(x) {
case 1:
case 2:
break;
}

這里遇到一個坑,有一個方法:

fun check(value: Any?): String = when (value) {
    is Int, Float, Double -> {
        if (value == 0) "value為0"
        else "value = $value"
    }
    else -> {
        "value為空"
    }
}

這個方法是用來判斷輸入的值,如果是IntFloatDouble類型的話就判斷是否為0,如果不是的就返回字符串value為空。

fun main(args: Array<String>) {
    println(check(1))
    println(check(11f))
    println(check(8.01))
    println(check(0))
}

打印結果為

....居然是這樣,跟我想的完全不一樣,為什么會這樣呢,看一下編譯后的代碼:

發現原因沒有,只有Int類型的才有加instanceof判斷,而另外兩個卻沒有,那么得為FloatDouble也加上is判斷才行。

fun check(value: Any?): String = when (value) {
    is Int, is Float, is Double -> {
        if (value == 0) "value為0"
        else "value = $value"
    }
    else -> {
        "value為空"
    }
}

再來看看編譯后的代碼:

還有打印的結果:

3. run、let、apply和with的區別

run函數

可以看出run是一個擴展函數,并且有返回值的,將最后一行做為返回,默認返回Unit,那么我們來寫個例子:

data class User(val name: String = "jowan", val age: Int = 24)

fun main(args: Array<String>) {
    val user = User()
    // runUnit類型為Unit
    val runUnit = user.run {
        println("runUnit:$this") // 打印runUnit:User(name=jowan, age=24)
    }
    println("runUnit type:$runUnit") // 打印runUnit type:kotlin.Unit
    // run類型為User
    val run = user.run {
        println("run:$this") // 打印run:User(name=jowan, age=24)
        User(age = 1)
    }
}

let函數

可以看出let也是一個擴展函數,與run函數一樣,同樣是有返回值,將最后一行做為返回,默認返回Unit,但是與run不同的時候,let有參數而run沒有:

data class User(val name: String = "jowan", val age: Int = 24)

fun main(args: Array<String>) {
    val user = User()
    // letUnit類型為Unit
    val letUnit = user.let {
        println("letUnit:$it")
    }
    println("letUnit type:$letUnit")
    // let類型為User
    val let = user.let {
        it ->
        println("let:$it")
        User(age = 2)
    }
}

apply函數

apply

可以看出apply函數也是一個擴展函數,也有返回值,默認返回該對象,與run的區別是run返回最后一行,apply返回該對象:

data class User(val name: String = "jowan", val age: Int = 24)

fun main(args: Array<String>) {
    val user = User()
    // apply類型為User
    val apply = user.apply {
        println("apply:$this") // 打印apply:User(name=jowan, age=24)
    }
    apply.let {
        println("apply let:$it") // 打印apply let:User(name=jowan, age=24)
    }
}

with函數

with

可以看出with函數不是擴展函數,與letapply有點像,同樣是有返回值,將最后一行做為返回,默認返回Unit,并且可以直接調用對象的方法和變量:

data class User(val name: String = "jowan", val age: Int = 24)

fun main(args: Array<String>) {
    val user = User()
    // withUnit類型為Unit
    val withUnit = with(user) {
        println("withUnit:$this") // 打印withUnit:User(name=jowan, age=24)
    }
    // with類型為User
    val with = with(user) {
        println("with:$this, name:$name, age:$age") // 打印with:User(name=jowan, age=24), name:jowan, age:24
        User(age = 111)
    }
    with.let {
        println("with let:$it") // 打印with let:User(name=jowan, age=111)
    }
}

小結

函數名 返回值 參數 函數類型
run 閉包返回 擴展函數
let 閉包返回 it 擴展函數
apply this 擴展函數
with 閉包返回 非擴展函數
2. 設置默認值

有這樣一個問題,通過Json獲取到的數據,如果獲取有空的值,那么就要將其改為默認值:

data class User(val name: String?, val age: Int?)

fun main(args: Array<String>) {
    var user = User(null, 23)
    println(user.name?.let { user.name } ?: "jowan")
}

這樣子寫是不是很麻煩,那么這里我們可以將其寫成一個方法,這樣子調用的話就很方便了:

data class User(val name: String?, val age: Int?)

fun <T> T?.getDefault(default: T): T = this?.let { this } ?: default

fun main(args: Array<String>) {
    val (name, _) = User(null, 23)
    println(name.getDefault("jowan"))
    val (_, age2) = User("jowan", null)
    println(age2.getDefault(23))
}
1. 獲取變量類型(getJavaClass)

使用::class.java來獲取變量類型,也可以用.javaClass來獲取類型。

fun main(args: Array<String>) {
    val i = "str"
    val classJava = i::class.java
    println(classJava) // 打印class java.lang.String
    val javaClass = i.javaClass
    println(javaClass) // 打印class java.lang.String
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。