Skip to content
This repository has been archived by the owner on Mar 11, 2023. It is now read-only.

[Kotlin In Action] Chapter Six Notes

spencercjh edited this page Nov 7, 2019 · 1 revision

6.Kotlin 的类型系统

这是我爱上Kotlin的一个很重要的原因。

可空类型和非空类型

从编译器层面对数据类型进行限制,确切地去确定一个对象究竟能不能为空。在Java语言中没有这样的限制,最常见的情景是:上层调用下层API,调用完获取结果的时候考虑是否要进行判空,点进函数实现查看它的retrun语句有没有返回空的,如果有返回空就要if (result==null){return something}等操作。

长期以往,其实很烦,特别是API设计,返回格式设计不合理的时候,代码里到处都是,全都是这些判空操作。而且程序员水平参差不齐,哪里忘记做判断了哪里就可能会爆出NPE

在Kotlin里就严格做出了限制,就像异常抛出一定要处理一样(尽管在Kotlin里去掉了这一点,前文有提及,这两个语言特性的设计思想不同),返回了可空类型就必须做额外处理!

安全调用运算符,猫王(Elvis)运算符,安全转换运算符,非空断言符

所有的所有都在这一个例子中体现啦:

import top.spencercjh.exercise.traverse.Node
import java.util.*
import kotlin.random.Random

object Service {
    val data = listOf(
        null,
        Node("Alice", 20),
        Node("Peter", 15),
        Node("Jack", 25),
        Node("Spencer", 22)
    )
    val random = Random(10)

    fun dbFunction(): List<Node?>? {
        return if (random.nextInt() % 2 == 0) {
            data
        } else {
            null
        }
    }

}

class TestAs(val name: String) {

    /*
     IDEA generated default code:
        override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as TestAs

        if (name != other.name) return false

        return true
    }*/
    override fun equals(other: Any?): Boolean {
        val otherTestAs = other as? TestAs ?: return false
        return otherTestAs.name == name
    }

    override fun hashCode(): Int {
        return name.hashCode()
    }
}

fun main() {
    val nullList: List<Node?>? = Service.dbFunction()
    println(nullList?.get(0) ?: "Null Object")
    val notNullList: List<Node?> = Service.dbFunction() ?: Collections.emptyList()
    println(notNullList)
    val a = TestAs("123")
    val b = TestAs("123")
    val c = TestAs("456")
    val d = Node("132", 1)
    val e = null
    assert(a == b)
    assert(b != c)
    assert(!c.equals(d))
    assert(a != e)
    // maybe throw NPE
    val assertNotNullList: List<Node?> = Service.dbFunction()!!
    println(assertNotNullList)
    // maybe throw RuntimeException
    val throwExceptionList: List<Node?> = Service.dbFunction() ?: throw RuntimeException("empty list")
    println(throwExceptionList)
}