Kotlin
惯用法

惯用法

延迟属性

延迟属性 ( Lazy property ) 仅在变量被初次调用时被计算和赋值,这个过程只会被执行一次

val expensiveData: String by lazy {
    println("Expensive data initialing")
    println("Loading.....")
    "This is expensiveData"
}
println(expensiveData)
println(expensiveData)

扩展函数

扩展函数能够被定义在类外,从而扩展类的功能,但扩展函数不能访问私有成员,不能被继承和重写

class Student(val name: String)
 
fun Student.sayName() {
    println(name)
}
 
fun main() {
    Student("Cherry").sayName()
}

创建单例对象

单例对象将初次访问时被初始化,且在整个程序的生命周期内只存在这一个实例

object Resource {
    val name = "Name"
    fun getName(): String {
        return name
    }
}

实例化抽象类

abstract class Person(val name: String, val age: Int) {
    abstract fun sayName()
}
 
fun main() {
    val myObject = object : Person("Cherry", 20) { // 使用object定义了一个匿名类
        override fun sayName() {
            TODO("Not yet implemented")
        }
    }
}

获取可空集合中的首个元素

val values = listOf(1, 2, 3, 4, 5, 6)
val negativeValues = values.filter { it < 0 }
println(values.firstOrNull()) // 1
println(negativeValues.firstOrNull()) // null
// .firstOrNull()将在首个元素为null时返回空

非空时调用(let)

let本质上是一个作用域函数,在指定的作用域内的函数

val value:Int? = 1
value?.let {
    println("Value is not null")
}
// 当value不为空时调用
class Student(val name: String)
 
fun main() {
    Student("Cherry").let {
        println("Student's name is ${it.name}")
    }
}
// 同时能够执行Lambda

除此之外的作用域函数(内联函数)还有:runwithapplyalso

try..catch异常处理

fun divide(a: Int, b: Int) = try {
    a / b
} catch (e: ArithmeticException) {
  e.printStackTrace()
    0
}

返回Unit的方法的构造者风格用法

fun arrayOfMinusOne(size: Int): Array<Int> {
    return arrayOf(size).apply { fill(-1) } // 使用了apply函数从而简化代码
}

Java 7的try-with-resource

Kotlin中并不含有IO流,此处调用的包为java.nio(新IO流)

val stream = Files.newInputStream(Paths.get("/home/cherry/TempDir/test.cpp"))
stream.buffered().reader().use { reader ->
    println(reader.readText())
}
// 实现了Closable接口的对象都能够调用.use{},无论是否发生异常,use{}均会自动关闭其调用者
// use中发生的异常会被抛出,不会被隐藏

需要泛型类型信息的泛型函数

fun <T> printElement(element: T) {
    println(element)
}
// <T>会被自动推导

可空布尔值

val b: Boolean? = null
if (b == true) {
    println("B is true")
} else {
    println("B is false of null")
}

交换两个变量

var a = "A"
var b = "B"
a = b.also { b = a }
// 在Lambda表达式中,b被赋予a的值,also返回b本身,a被赋予b的值

标记为未完成的代码(TODO)

fun notImplementedFunction() {
    TODO() // TODO始终抛出异常,其返回值为Nothing
}

Nothing

Nothing与Java中的void不同,表示确实没有值,Nothing不具有值,且不能被实例化,但Nothing是所有类型的子类型,Nothing能够:

作为函数的返回值类型,明确这是一个「不会返回的函数」

fun throwException(): Nothing {
    throw RuntimeException("This is a exception") // 抛出异常的函数始终不会返回
}
// 还有无限循环,但是使用很少

作为泛型变量通用的、空白的临时填充

val emptyList: List<Nothing> = listOf()
var intList: List<Int> = emptyList

语法层面的完整化

fun sayMyName(first: String, second: String) {
    val name = if (first == "Walter" && second == "White") {
        "Heisenberg"
    } else {
        return // 由于Nothing是任意类型的子类型,可以直接用与String类型的name(语法层面)
    }
    println(name)
}